Extending existing filters
By default InfiniteTable
has the following default filter types:
string
number
and each of them has a collection of operators that are supported - see filterTypes
for the respective list of supported operators.
You may find those operators limiting - but it's easy to extend them and add new operators or even new filter types.
Adding new operators to existing filter types
You can import defaultFilterTypes
from the root of the package.
import { defaultFilterTypes } from '@infinite-table/infinite-react';
// add new operators for the `string` filter type
defaultFilterTypes.string.operators.push({
name: 'notContains',
component: { Icon: ReactComponentForIcon }
label: 'Not Contains',
fn: ({currentValue, filterValue }) => {
return typeof currentValue === 'string' &&
typeof filterValue == 'string' &&
!currentValue.toLowerCase().includes(filterValue.toLowerCase())
}
})
Note
When you import the named defaultFilterTypes
value and extend it, that will affect all InfiniteTable
components in your application.
If you don't want that, you need to use the filterTypes
prop of the <DataSource />
component. Either build an entirely new object for filterTypes
, or start by cloning defaultFilterTypes
and extend it.
The string
columns have a new Not includes
operator.
import * as React from 'react'; import { DataSourceData, InfiniteTable, InfiniteTablePropColumns, DataSource, defaultFilterTypes, } from '@infinite-table/infinite-react'; type Developer = { id: number; firstName: string; lastName: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; salary: number; }; defaultFilterTypes.string.operators.push({ name: 'Not contains', label: 'Not Contains', fn: ({ currentValue, filterValue, emptyValues }) => { if ( emptyValues.includes(currentValue) || emptyValues.includes(filterValue) ) { return true; } return ( typeof currentValue === 'string' && typeof filterValue == 'string' && !currentValue.toLowerCase().includes(filterValue.toLowerCase()) ); }, }); const data: DataSourceData<Developer> = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + `/developers1k-sql?`) .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id', type: 'number', defaultWidth: 100, }, firstName: { field: 'firstName', }, stack: { field: 'stack' }, salary: { field: 'salary', type: 'number', }, currency: { field: 'currency', defaultFilterable: false }, }; const domProps = { style: { height: '100%', }, }; export default () => { return ( <> <React.StrictMode> <DataSource<Developer> data={data} primaryKey="id" defaultFilterValue={[]} filterDelay={0} filterMode="local" > <InfiniteTable<Developer> domProps={domProps} columnDefaultWidth={150} columnMinWidth={50} columns={columns} /> </DataSource> </React.StrictMode> </>
Adding new filter types
If the existing filter types are not enough, it's easy to add new ones.
As already mentioned, you can either update the value of defaultFilterTypes
or use the filterTypes
prop of the <DataSource />
component. Updating the value defaultFilterTypes
will affect all your InfiniteTable
DataGrid components.
import { defaultFilterTypes } from '@infinite-table/infinite-react';
defaultFilterTypes.bool = {
defaultOperator: 'eq',
emptyValues: [null],
operators: [
{
name: 'eq',
label: 'Equals',
fn: ({ currentValue, filterValue }) => currentValue === filterValue,
},
],
};
import { DataSource } from '@infinite-table/infinite-react';
<DataSource
filterTypes={{
bool: {
defaultOperator: 'eq',
emptyValues: [null],
operators: [
{
name: 'eq',
label: 'Equals',
fn: ({ currentValue, filterValue }) => currentValue === filterValue,
},
],
},
}}
/>;
Note
When passing filterTypes
to the <DataSource />
component, the object will be merged with the defaultFilterTypes
. As a result, the existing string
and number
filterTypes will be preserved, unless explicitly overridden.
The canDesign
column is using a custom bool
filter type with a custom filter editor.
import * as React from 'react'; import { InfiniteTable, InfiniteTablePropColumns, DataSource, components, useInfiniteColumnFilterEditor, } from '@infinite-table/infinite-react'; const { CheckBox } = components; type Developer = { id: number; firstName: string; canDesign: boolean; stack: string; hobby: string; }; const dataSource: Developer[] = [ { id: 1, firstName: 'John', canDesign: true, stack: 'frontend', hobby: 'gaming', }, { id: 2, firstName: 'Jane', canDesign: false, stack: 'backend', hobby: 'reading', }, { id: 3, firstName: 'Jack', canDesign: true, stack: 'frontend', hobby: 'gaming', }, { id: 4, firstName: 'Jill', canDesign: false, stack: 'backend', hobby: 'reading', }, { id: 5, firstName: 'Seb', canDesign: false, stack: 'backend', hobby: 'reading', }, ]; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id', type: 'number', defaultWidth: 100, }, canDesign: { field: 'canDesign', filterType: 'bool', renderValue: ({ value }) => (value ? 'Yes' : 'No'), }, firstName: { field: 'firstName', }, stack: { field: 'stack' }, }; const domProps = { style: { height: '100%', }, }; function BoolFilterEditor() { const { value, setValue, className } = useInfiniteColumnFilterEditor<Developer>(); return ( <div className={className} style={{ textAlign: 'center' }}> <CheckBox checked={value} onChange={(newValue) => { if (value === true) { // after the value was true, make it go to indeterminate state newValue = null; } if (value === null) { // from indeterminate, goto false newValue = false; } setValue(newValue); }} /> </div> ); } export default () => { return ( <> <React.StrictMode> <DataSource<Developer> data={dataSource} primaryKey="id" defaultFilterValue={[]} filterDelay={0} filterTypes={{ bool: { defaultOperator: 'eq', emptyValues: [null], components: { FilterEditor: BoolFilterEditor, FilterOperatorSwitch: () => null, }, operators: [ { name: 'eq', label: 'Equals', fn: ({ currentValue, filterValue }) => currentValue === filterValue, }, ], }, }} > <InfiniteTable<Developer> domProps={domProps} columnDefaultWidth={150} columnMinWidth={50} columns={columns} /> </DataSource> </React.StrictMode> </>