Skip to main content

Filters

Filters are one of the most powerful features of the React DataGrid. In fact, we've built filters into their own stand alone behavior that can be plugged in so if you are not using Filters, they dont add any overhead to your application. The first thing you can do is import the createFilterBehavior function from the @grid-core/createFilterBehavior package.

import { createFilterBehavior } from "@grid-core/createFilterBehavior";

Then you can add the behavior to the gridOptions object.

const gridOptions = {
behaviors: [createFilterBehavior({})]
}

There are two types of filters: column filters and global filters.

Global Filters

There are two types of global filters: quick find and filter builder. The quick find filter is a simple text box that allows you to search for a value in any column. The advanced filters allow you to create a filter for each column. The filter builder is displayed in a popup window. The quick find filter is displayed in the header of the grid.

Global Filter

The global filter is a simple text box that allows you to search for a value in any column. To enable the quick find filter, you can set the enableGlobalSearch property to true (default) and add createFilterBehavior to the behaviors array.

const gridOptions = {
behaviors: [createFilterBehavior({})],
toolbarOptions: {
enableGlobalSearch: true
}
}

Below is the full example:

Live Editor
Result
Loading...
tip

There is a example that shows how to add your own global filter, customize filters, and more. You can find it here

As soon as you add the behavior, the toolbar will display a quick find filter. You can type in the filter and the grid will display only the rows that match the filter.

Filter Builder

The filter builder is a popup window that allows you to create a filter for each column. It allows you to build complex filters using the AND and OR operators. The AND/OR operators can be nested in a tree structure to create complex filters. To enable the filter builder, can import the FilterBuidler component and set filterBuilderRenderer property on the toolbarOptions object.

import { FilterBuidler } from "@ezgrid/grid-react";
const gridOptions = {
behaviors: [createFilterBehavior({})],
toolbarOptions: {
filterBuilderRenderer: ({ node }) => <FilterBuidler node={node} />
},
}

Below is the full example:

Live Editor
Result
Loading...
tip

There is a example that shows the filter builder here

Quick Find

Although not technically a filter, the quick find textbox is a simple text box that allows you to search for a value in any column. Once you type in the value, the grid will show the number of rows that match the criteria and let you navigate between the rows that match the criteria. It will highlight the cell that matches the filter with a yellow background. You can customize this background using the below css

.ezgrid-dg-quick-find-cell {
background-color: rgba(234, 208, 10, .5)
}

To enable/disable the quick find filter, can set the enableQuickFind property to true (default). Unlike the global filters, the quick find filter is not a behavior. It is a property of the toolbarOptions object. It is enabled by default. To disable it, set the enableQuickFind property to false. Since its enabled by default, any of the examples we have shown so far will have the quick find filter enabled.

const gridOptions = {
toolbarOptions: {
enableQuickFind: true
}
}

Column Filters

Column filters are filters that are applied to a single column. To add a column filter to a column, you can add the filterOptions property to the column object. Below is the definition of the FilterOptions interface.

    export interface FilterOptions {
filterCompareFunction?: (item: unknown, col: ColumnOptions, value: unknown) => boolean;
filterConverterFunction?: (item: unknown, col: ColumnOptions, value: unknown) => unknown;
filterDeserializerFunction?: (col: ColumnOptions, value: unknown) => unknown;
filterComboBoxDataProvider?: unknown[];
filterComboBoxLabelField?: string;
filterComboBoxDataField?: string;
filterComboBoxBuildFromGrid?: boolean;
filterComboBoxBuildFromGridHierarchy?: boolean;
filterDateRangeOptions?: (DateRangeType | { type: string, start: Date, end: Date })[];
filterOperation?: FilterOperation;
filterComparisionType?: FilterComparisionType;
excludeFromQuickFind?: boolean;
filterWaterMark?: string;
delayedChangeDuration?: number;
useLabelFunctionForFilterCompare?: boolean;
blankValuesLabel?: string;
filterRenderer?: (
props: RendererProps
) => unknown;
}

The documentation for the above properties can be found here

The filterWaterMark property is used to show a watermark in the filter textbox. The filterWaterMark property is only used for the TextBox filter. The watermark is shown when the filter is empty.

The delayedChangeDuration property is used to delay the filter change event. This is useful when you want to delay the filter change event until the user stops typing. The default value is 0. If you set the value to 500, the filter change event will be fired after 500 milliseconds of inactivity. This is useful when you want to delay the filter change event until the user stops typing. The default value is 0. If you set the value to 500, the filter change event will be fired after 500 milliseconds of inactivity.

The useLabelFunctionForFilterCompare property is used to determine if the label function should be used to compare the filter value with the cell value. The default value is false. If you set the value to true, the label function will be used to compare the filter value with the cell value. This is useful when you want to compare the filter value with the cell value using the label function. The default value is false. If you set the value to true, the label function will be used to compare the filter value with the cell value.

The blankValuesLabel property is used to determine the label that should be used for blank values. The default value is Constants.NONE_LABEL.

The filterRenderer property is used to render a custom filter. The default value is undefined. If you set the value to a function, the function will be used to render the filter. This is useful when you want to render a custom filter. The default value is undefined. If you set the value to a function, the function will be used to render the filter. We will see an example of this later.

The filterComboBoxDataProvider property is used to set the data provider for the ComboBox filter. The default value is undefined. If you set the value to an array, the array will be used as the data provider for the ComboBox/MultiSelect filter. This is useful when you want to set the data provider for the ComboBox filter. The default value is undefined, because the ComboBox filter will use the data provider of the grid. If you set the value to an array, the array will be used as the data provider for the ComboBox/MultiSelect filter.

The filterComboBoxLabelField/filterComboBoxDataField properties are used in conjunction with the filterComboBoxDataProvider property to set the label and data fields for the ComboBox filter.

The filterComboBoxBuildFromGridHierarchy property is used when you have an entire hierarhcy in a single column (as opposed to multiple hierarchical columns.) The grouping example shows how to do this. You can see this example here: http://reactdatagrid.com/examples?example=Grouping

To help you setup filters quickly, we expose a set of helper functions that will create the filterOptions object for you. The helper functions are

  • createDateFilterOptions
  • createMultiSelectFilterOptions
  • createSelectFilterOptions
  • createTextInputFilterOptions
  • createTriStateCheckBoxFilterOptions
  • createNumericRangeFilterOptions

We will see examples of each of these helper functions below.

TextInput Filter

Lets add a column filter to the firstName column. We will use a TextBox filter with a filterOperation of "wildcard".

Live Editor
Result
Loading...

As you can see, we are using the createTextInputFilterOptions function to create the filterOptions object. This function takes a FilterOperation as a parameter. The FilterOperation enum has the following values:

Note: When you apply a filter, an icon will appear on the toolbar with a number next to it indicating the number of filters applied. You can click on the icon to see the filters applied. You can also click on the icon to clear the filters. To disable this behavior, set the enableFilterChips property on the toolbarOptions object to false.

export enum FilterOperation {
"None" = "None",
"Equals" = "Equals",
"NotEquals" = "NotEquals",
"BeginsWith" = "BeginsWith",
"Wildcard" = "Wildcard",
"EndsWith" = "EndsWith",
"Contains" = "Contains",
"DoesNotContain" = "DoesNotContain",
"GreaterThan" = "GreaterThan",
"LessThan" = "LessThan",
"GreaterThanEquals" = "GreaterThanEquals",
"LessThanEquals" = "LessThanEquals",
"InList" = "InList",
"NotInList" = "NotInList",
"Between" = "Between",
"IsNotNull" = "IsNotNull",
"IsNull" = "IsNull",
}

MultiSelect Filter

Lets add a MultiSelect ComboBox filter to the stateCode column. We will use the filterComboBoxDataProvider property to set the data provider for the ComboBox filter. We will use the filterComboBoxLabelField and filterComboBoxDataField properties to set the label and data fields for the ComboBox filter.

Live Editor
Result
Loading...

Notice that the dropdown has the full name of the state. This is because we are using the filterComboBoxLabelField and filterComboBoxDataField properties to set the label and data fields for the ComboBox filter. However, in case the data in the datagrid already contains the full name of the state, we can use the filterComboBoxBuildFromGrid property. In fact, this is the default behavior. If you set the filterComboBoxBuildFromGrid property to true or leave it unset, the ComboBox filter will use the data in the datagrid to build the data provider for the ComboBox filter. This is useful when you want to use the data in the datagrid to build the data provider for the ComboBox filter. Lets try this out with the Department column.

Live Editor
Result
Loading...

In the example above, the department filter is built from the grid, while the stateCode filter is built from the Employee.allStates array.

Now, lets take a look at some of the other filter types, namely the Date, Number and CheckBox filters. Lets modify the example above to add a Date filter to the hireDate column, a Number filter to the annualSalary column and a CheckBox filter to the isActive column.

Live Editor
Result
Loading...

As you can see, the tri state checkbox filter is used for the isActive column, and allows you to filter by true, false or both. The numeric range filter is used for the annualSalary column, and allows you to filter by a range of values. The date filter is used for the hireDate column, and allows you to filter by a range of dates.

ComboBox Filter

Like the MultiSelect Filter, the ComboBox filter is a dropdown filter. However, the ComboBox filter allows you to select only one item at a time. The ComboBox filter is useful when you want to filter by a single value. Similar to the MultiSelect filter, the ComboBox filter can be built from the grid data, or from an array of data. Lets take a look at an example of the ComboBox filter using the filterComboBoxDataProvider property as well as the filterComboBoxBuildFromGrid property and will show you how to use the filterComboBoxLabelField and filterComboBoxDataField properties.

Lets modify the example above to add a ComboBox filter to the department column, and a ComboBox filter to the stateCode column.

Live Editor
Result
Loading...

As you can see, the ComboBox filter is used for the department column, and allows you to filter by a single department. The ComboBox filter is used for the stateCode column, and allows you to filter by a single state. The ComboBox filter is built from the Employee.allStates array, so it has a label and data field. The label field is used to display the label in the ComboBox, and the data field is used to filter the data. The department column is built from the grid data, so it uses the default label and data fields from the grid data.

Date Filter

The Date filter is by default, a range filter. When add it without an options, it will show all the available date range options. These are listed below:

export enum DateRangeType {
"Last60Minutes" = "Last 60 Minutes",
"Last12Hours" = "Last 12 Hours",
"Last24Hours" = "Last 24 Hours",
"Last7Days" = "Last 7 Days",
"ThisHour" = "This Hour",
"LastHour" = "Last Hour",
"NextHour" = "Next Hour",
"Today" = "Today",
"Yesterday" = "Yesterday",
"Tomorrow" = "Tomorrow",
"ThisWeek" = "This Week",
"LastWeek" = "Last Week",
"NextWeek" = "Next Week",

"Next2Weeks" = "Next 2 Weeks",
"ThisMonth" = "This Month",
"LastMonth" = "Last Month",
"NextMonth" = "Next Month",
"ThisYear" = "This Year",
"LastYear" = "Last Year",
"NextYear" = "Next Year",
"Custom" = "Custom",
"ThisQuarter" = "This Quarter",
"NextQuarter" = "Next Quarter",
"LastQuarter" = "Last Quarter",

}

When you add the date filter, you can specify the date range options that you want to show. For example, if you want to show only the last years, this year and custom options, you can do the following:

Live Editor
Result
Loading...

Also, you can specify your own date range types:

    function App() {
const columns = [
{
...createColumn("hireDate", "date", "Hire Date"),
filterOptions: createDateFilterOptions([DateRangeType.Custom,
{ type: "2010-2020", start: new Date(2010, 0, 1), end: new Date(2020, 11, 31) },
{ type: "2000-2010", start: new Date(2000, 0, 1), end: new Date(2010, 11, 31) },
{ type: "1990-2000", start: new Date(1990, 0, 1), end: new Date(2000, 11, 31) }] ),
},
createColumn("lastName", "string", "Last Name"),
createColumn("annualSalary", "currency", "Salary"),
createColumn("stateCode", "string", "Territory"),
createColumn("department", "string", "Department"),
];

return (
<ReactDataGrid
style={{ height: "400px", width: "100%" }}
gridOptions={{
behaviors:[createFilterBehavior({})],
dataProvider: Employee.getAllEmployees(),
uniqueIdentifierOptions: {
useField: "employeeId",
},
columns,
enableFilters: true,
}}
/>
);
}

Numeric Range Filter

The Numeric Range filter is by default, a range filter. Its usually used with numeric columns, but it can be used with string columns as well. It shows two input boxes for the start and end values. Lets add a numeric range filter to the annual salary column:

Live Editor
Result
Loading...

Customizing Filters

Just like the column headers, you can customize the filters as well. Remember, the filters are just React components, and they are very very simple. For example, lets take a look at the source code of the TextInputFilter:


const TextInputFilter: FC<RendererProps> = ({ node }) => {
const textInputRef = useRef<HTMLInputElement>(null);
const api = getApi(node);
const col = node.columnPosition?.column;
const opts = col?.filterOptions;
const columnIdentifier = col?.uniqueIdentifier!;
const debouncedChange = debounce(() => {
api.setFilterValue(columnIdentifier, textInputRef.current?.value);
}, opts?.delayedChangeDuration || TEXT_INPUT_CHANGE_DELAY);
let currentValue = "";
if (col?.uniqueIdentifier) {
currentValue = api.getFilterValue(columnIdentifier) as string || "";
}
useEffect(() => {
if (textInputRef.current) {
textInputRef.current.value = currentValue;
}
}, [currentValue]);
return createTextField(node.gridOptions, {
type: "text", placeholder: opts?.filterWaterMark || "Search...", onChange: debouncedChange, ref: textInputRef,
style: { width: "100%" }
});
};

export const TextInputFilterRenderer = (props: RendererProps) => <TextInputFilter key={props.node.key} {...props} />;

As you can see, this is barely 20 lines of code. Lets take a look at the NumericRangeFilter:

export const NumericRangeFilter: FC<RangeFilterRendererProps> = ({ node, filterBuilderMode, onValueChanged, value, numeric }) => {
const startRef = useRef<HTMLInputElement>(null);
const endRef = useRef<HTMLInputElement>(null);
const api = getApi(node);
const col = node.columnPosition?.column;
const columnIdentifier = col?.uniqueIdentifier!;
const debouncedChange = debounce(() => {
let value: RangeFilter | undefined = undefined;
if (startRef.current?.value && endRef.current?.value) {
value = {
start: numeric === false ? startRef.current?.value : Number(startRef.current?.value),
end: numeric === false ? endRef.current?.value : Number(endRef.current?.value)
};
} else if (startRef.current?.value === "" && endRef.current?.value === "") {
if (!filterBuilderMode)
api.clearFilterValue(columnIdentifier);
}
if (value) {
if (!filterBuilderMode)
api.setFilterValue(columnIdentifier, value);
else
onValueChanged?.(value);
}
}, col?.filterOptions?.delayedChangeDuration || TEXT_INPUT_CHANGE_DELAY);
let currentValue: RangeFilter | undefined = undefined;
if (columnIdentifier) {
currentValue = (filterBuilderMode ? value : api.getFilterValue(columnIdentifier)) as RangeFilter | undefined;
}
useEffect(() => {
if (startRef.current && endRef.current) {
if (currentValue?.start && currentValue?.end) {
startRef.current.value = (currentValue.start || "").toString();
endRef.current.value = (currentValue.end || "").toString();
} else {
startRef.current.value = "";
endRef.current.value = "";
}
}
}, [currentValue?.start, currentValue?.end]);
return <div className={`${GRID_CONSTANTS.CSS_PREFIX}numeric-range`} >
{
createTextField(node.gridOptions, { ref: startRef, type: "number", onChange: debouncedChange, placeholder: ">=" })
}
<div style={{ width: "5px" }}></div>
{
createTextField(node.gridOptions, { ref: endRef, type: "number", onChange: debouncedChange, placeholder: "<=" })
}
</div>;
};
const NumericRangeFilterRenderer = (props: RendererProps) => <NumericRangeFilter key={props.node.key} {...props} />;

And below is the Select filter:

    const SelectFilter: FC<RendererProps> = ({ node }) => {
const allValue = {
name: ALL_LABEL,
value: ALL_LABEL
};
const api = getApi(node);
const col = node.columnPosition?.column;
const options = col ? [allValue, ...api.getDistinctFilterValues(col)] : [allValue];
const columnIdentifier = node.columnPosition?.column.uniqueIdentifier!;
let currentValue = ALL_LABEL;
if (node.columnPosition?.column.uniqueIdentifier) {
currentValue = api.getFilterValue(columnIdentifier) as string || ALL_LABEL;
}
const changeHandler = (newVal: unknown) => {
api.setFilterValue(columnIdentifier, newVal);
};
return createSelectField(node.gridOptions, {
onChange: changeHandler,
value: currentValue,
options: options as NameValue[],
});
};

const SelectFilterRenderer = (props: RendererProps) => <SelectFilter key={props.node.key} {...props} />;

You will notice that most of the logic to run the filter, store its state, etc is abstracted away into the behavior and made available to all the filter renderers via the api. You can leverage this api to create your own custom filters. For example, lets say you want to make a range slider filter for the annual salary column. Here is how you can do it:

Live Editor
Result
Loading...

So there it is, with barely 20 lines of code, you can create a custom filter for your grid!

Conclusion

Filters are among the most powerful features of the grid. While this guide was a quick overview of the filter feature, we have a lot more to offer.

  • There is an example of all the filters in action here.
  • There is an example of how these filters internally switch to Material UI MUI components here.
  • There is a full running example of the Filter Builder here: here.
  • There is an example of how to integrate filtering with server side data here: here.
  • There is an example of how filters integrate with hierarchical data here: here.
  • There is an example of the Custom Toolbar with an external filter here: here.
tip

All the examples above have a View Source link that you can use to look at the source code.

Reference Code

The code for all the editors, filters, toolbar, menu renderers, etc is available in the reference folder of the Samples Repo on Github. You will need to update the import for ReactDataGrid to point to the local version of the grid.

import { ReactDataGrid } from '@ezgrid/grid-react';

In case the code does not compile, please let us know, there may be a mismatch in the version of the grid you are using and the version of the samples repo and we will be happy to provide you with copy of the samples repo that works with your version of the grid in case you are using a version of the grid that is not the latest.