Data Grid - Filtering
Easily filter your rows based on one or several criteria.
The filters can be modified through the data grid interface in several ways:
- By opening the column menu and clicking the Filter menu item.
- By clicking the Filters button in the data grid toolbar (if enabled).
Each column type has its own filter operators. The demo below lets you explore all the operators for each built-in column type.
See the dedicated section to learn how to create your own custom filter operator.
Single and multi-filtering
Multi-filtering
The following demo lets you filter the rows according to several criteria at the same time.
One filter per column
You can also limit to only one filter per column while still allowing to filter other columns. For this, use the filterColumns
and getColumnForNewFilter
props available in slotProps.filterPanel
.
Use cases
- Sometimes it's a limitation of some server-side filtering APIs to only allow one filter per column.
- You can also write custom logic to prevent some columns from being shown as possible filters.
This demo implements a basic use case to prevent showing multiple filters for one column.
Disable action buttons
To disable Add filter
or Remove all
buttons, pass disableAddFilterButton
or disableRemoveAllButton
to componentsProps.filterPanel
.
Header filters
Header filters add a new header row that lets users quickly filter the columns. The filters added on the filter panel are synchronized with the header filters and vice versa.
You can switch between different operators by clicking the operator button in the header filter cell or pressing Ctrl+Enter (or ⌘ Command+Enter on macOS) when focusing on a header filter cell.
Simple header filters
You can disable default filter panel using disableColumnFilter
prop and only show the default operator by passing slots.headerFilterMenu
as null
.
Customize header filters
There are multiple ways to customize header filters.
renderHeaderFilter
method
You can use the renderHeaderFilter
method of the GridColDef
to customize the header filter cell for a specific column.
const columns: GridColDef[] = [
{
field: 'isAdmin',
renderHeaderFilter: (params: GridColumnHeaderParams<R, V, F>) => (
<MyCustomHeaderFilter {...params} />
),
},
];
The following demo uses the renderHeaderFilter
method to customize the header filter cell for the isAdmin
column and hide the filter cell for the phone
column.
Customize using filterOperators
If the filter operator has a custom InputComponent
, the same component is being used for the header filter.
When rendered as a header filter, the InputComponent
also receives the headerFilterMenu
and clearButton
props that contain the filter operator menu and clear button.
headerFilterCell
slot
You can use slots.headerFilterCell
to customize the header filter cell completely. Since the default slot component handles keyboard navigation and focus management, you may have to handle them yourself if you are using a custom component.
Additionally, slots.headerFilterMenu
could also be used to customize the menu of the header filter cell.
<DataGridPro {...data} slots={{ headerFilterCell: MyCustomHeaderFilterCell }} />
Pass filters to the Data Grid
Structure of the model
The full typing details can be found on the GridFilterModel API page.
The filter model is composed of a list of items
and a logicOperator
:
The items
A filter item represents a filtering rule and is composed of several elements:
filterItem.field
: the field on which the rule applies.filterItem.value
: the value to look for.filterItem.operator
: name of the operator method to use (e.g. contains), matches thevalue
key of the operator object.filterItem.id
(): required when multiple filter items are used.
The logicOperator
The logicOperator
tells the data grid if a row should satisfy all (AND
) filter items or at least one (OR
) in order to be considered valid.
// Example 1: get rows with rating > 4 OR isAdmin = true
const filterModel: GridFilterModel = {
items: [
{ id: 1, field: 'rating', operator: '>', value: '4' },
{ id: 2, field: 'isAdmin', operator: 'is', value: 'true' },
],
logicOperator: GridLogicOperator.Or,
};
// Example 2: get rows with rating > 4 AND isAdmin = true
const filterModel: GridFilterModel = {
items: [
{ id: 1, field: 'rating', operator: '>', value: '4' },
{ id: 2, field: 'isAdmin', operator: 'is', value: 'true' },
],
logicOperator: GridLogicOperator.And,
};
If no logicOperator
is provided, the data grid will use GridLogicOperator.Or
by default.
Initialize the filters
To initialize the filters without controlling them, provide the model to the initialState
prop.
<DataGrid
initialState={{
filter: {
filterModel: {
items: [{ field: 'rating', operator: '>', value: '2.5' }],
},
},
}}
/>
Controlled filters
Use the filterModel
prop to control the filter applied on the rows.
You can use the onFilterModelChange
prop to listen to changes to the filters and update the prop accordingly.
<DataGrid
filterModel={{
items: [{ field: 'rating', operator: '>', value: '2.5' }],
}}
/>
Disable the filters
For all columns
Filters are enabled by default, but you can easily disable this feature by setting the disableColumnFilter
prop.
<DataGrid disableColumnFilter />
For some columns
To disable the filter of a single column, set the filterable
property in GridColDef
to false
.
In the example below, the rating column can not be filtered.
<DataGrid columns={[...columns, { field: 'rating', filterable: false }]} />
Customize the operators
The full typing details can be found on the GridFilterOperator API page.
An operator determines if a cell value should be considered as a valid filtered value.
The candidate value used by the operator is the one corresponding to the field
attribute or the value returned by the valueGetter
of the GridColDef
.
Each column type comes with a default array of operators. You can get them by importing the following functions:
Column type | Function |
---|---|
string |
getGridStringOperators() |
number |
getGridNumericOperators() |
boolean |
getGridBooleanOperators() |
date |
getGridDateOperators() |
dateTime |
getGridDateOperators(true) |
singleSelect |
getGridSingleSelectOperators() |
You can find more information about the supported column types in the columns section.
Create a custom operator
If the built-in filter operators are not enough, creating a custom operator is an option.
A custom operator is defined by creating a GridFilterOperator
object.
This object has to be added to the filterOperators
attribute of the GridColDef
.
The main part of an operator is the getApplyFilterFn
function.
When applying the filters, the data grid will call this function with the filter item and the column on which the item must be applied.
This function must return another function that takes the cell value as an input and return true
if it satisfies the operator condition.
const operator: GridFilterOperator = {
label: 'From',
value: 'from',
getApplyFilterFn: (filterItem: GridFilterItem, column: GridColDef) => {
if (!filterItem.field || !filterItem.value || !filterItem.operator) {
return null;
}
return (params: GridCellParams): boolean => {
return Number(params.value) >= Number(filterItem.value);
};
},
InputComponent: RatingInputValue,
InputComponentProps: { type: 'number' },
};
In the demo below, you can see how to create a completely new operator for the Rating column.
Wrap built-in operators
You can create custom operators that re-use the logic of the built-in ones.
In the demo below, the selected rows are always visible even when they don't match the filtering rules.
Multiple values operator
You can create a custom operator which accepts multiple values. To do this, provide an array of values to the value
property of the filterItem
.
The valueParser
of the GridColDef
will be applied to each item of the array.
The filtering function getApplyFilterFn
must be adapted to handle filterItem.value
as an array.
Below is an example for a "between" operator, applied on the "Quantity" column.
{
label: 'Between',
value: 'between',
getApplyFilterFn: (filterItem: GridFilterItem) => {
if (!Array.isArray(filterItem.value) || filterItem.value.length !== 2) {
return null;
}
if (filterItem.value[0] == null || filterItem.value[1] == null) {
return null;
}
return ({ value }): boolean => {
return value != null && filterItem.value[0] <= value && value <= filterItem.value[1];
};
},
InputComponent: InputNumberInterval,
}
Remove an operator
To remove built-in operators, import the method to generate them and filter the output to fit your needs.
// Only keep '>' and '<' default operators
const filterOperators = getGridNumericOperators().filter(
(operator) => operator.value === '>' || operator.value === '<',
);
In the demo below, the rating
column only has the <
and >
operators.
Custom input component
The value used by the operator to look for has to be entered by the user. On most column types, a text field is used. However, a custom component can be rendered instead.
In the demo below, the rating
column reuses the numeric operators but the rating component is used to enter the value of the filter.
Custom column types
When defining a custom column type, by default the data grid will reuse the operators from the type that was extended. The filter operators can then be edited just like on a regular column.
const ratingColumnType: GridColTypeDef = {
extendType: 'number',
filterOperators: getGridNumericOperators().filter(
(operator) => operator.value === '>' || operator.value === '<',
),
};
Custom filter panel
You can customize the rendering of the filter panel as shown in the component section of the documentation.
Customize the filter panel content
The customization of the filter panel content can be performed by passing props to the default <GridFilterPanel />
component.
The available props allow overriding:
- The
logicOperators
(can containsGridLogicOperator.And
andGridLogicOperator.Or
) - The order of the column selector (can be
"asc"
or"desc"
) - Any prop of the input components
Input components can be customized by using two approaches.
You can pass a sx
prop to any input container or you can use CSS selectors on nested components of the filter panel.
More details are available in the demo.
Props | CSS class |
---|---|
deleteIconProps |
MuiDataGrid-filterFormDeleteIcon |
logicOperatorInputProps |
MuiDataGrid-filterFormLogicOperatorInput |
columnInputProps |
MuiDataGrid-filterFormColumnInput |
operatorInputProps |
MuiDataGrid-filterFormOperatorInput |
valueInputProps |
MuiDataGrid-filterFormValueInput |
The value input is a special case, because it can contain a wide variety of components (the one provided or your custom InputComponent
).
To pass props directly to the InputComponent
and not its wrapper, you can use valueInputProps.InputComponentProps
.
Customize the filter panel position
The demo below shows how to anchor the filter panel to the toolbar button instead of the column header.
Server-side filter
Filtering can be run server-side by setting the filterMode
prop to server
, and implementing the onFilterModelChange
handler.
The example below demonstrates how to achieve server-side filtering.
Quick filter
Quick filter allows filtering rows by multiple columns with a single text input.
To enable it, you can add the <GridToolbarQuickFilter />
component to your custom toolbar or pass showQuickFilter
to the default <GridToolbar />
.
By default, the quick filter considers the input as a list of values separated by space and keeps only rows that contain all the values.
Initialize the quick filter values
The quick filter values can be initialized by setting the filter.filterModel.quickFilterValues
property of the initialState
prop.
<DataGrid
initialState={{
filter: {
filterModel: {
items: [],
quickFilterValues: ['quick', 'filter'],
},
},
}}
/>
Custom filtering logic
The logic used for quick filter can be switched to filter rows that contain at least one of the values specified instead of testing if it contains all of them.
To do so, set quickFilterLogicOperator
to GridLogicOperator.Or
as follow:
initialState={{
filter: {
filterModel: {
items: [],
quickFilterLogicOperator: GridLogicOperator.Or,
},
},
}}
With the default settings, quick filter will only consider columns with types 'string'
,'number'
, and 'singleSelect'
.
- For
'string'
and'singleSelect'
columns, the cell's formatted value must contain the value - For
'number'
columns, the cell's formatted value must equal the value
To modify or add the quick filter operators, add the property getApplyQuickFilterFn
to the column definition.
This function is quite similar to getApplyFilterFn
.
This function takes as an input a value of the quick filter and returns another function that takes the cell value as an input and returns true
if it satisfies the operator condition.
In the example below, a custom filter is created for the date
column to check if it contains the correct year.
getApplyQuickFilterFn: (value: string) => {
if (!value || value.length !== 4 || !/\d{4}/.test(value)) {
// If the value is not a 4 digit string, it can not be a year so applying this filter is useless
return null;
}
return (params: GridCellParams): boolean => {
return params.value.getFullYear() === Number(value);
};
};
To remove the quick filtering on a given column set getApplyQuickFilterFn: undefined
.
In the demo below, the column "Name" is not searchable with the quick filter, and 4 digits figures will be compared to the year of column "Created on."
Parsing values
The values used by the quick filter are obtained by splitting with space.
If you want to implement a more advanced logic, the <GridToolbarQuickFilter/>
component accepts a prop quickFilterParser
.
This function takes the string from the search text field and returns an array of values.
If you control the quickFilterValues
either by controlling filterModel
or with the initial state, the content of the input must be updated to reflect the new values.
By default, values are joint with a spaces. You can customize this behavior by providing quickFilterFormatter
.
This formatter can be seen as the inverse of the quickFilterParser
.
For example, the following parser allows to search words containing a space by using the ','
to split values.
<GridToolbarQuickFilter
quickFilterParser={(searchInput) =>
searchInput.split(',').map((value) => value.trim())
}
quickFilterFormatter={(quickFilterValues) => quickFilterValues.join(', ')}
debounceMs={200} // time before applying the new quick filter value
/>
In the following demo, the quick filter value "Saint Martin, Saint Lucia"
will return rows with country is Saint Martin or Saint Lucia.
apiRef
The grid exposes a set of methods that enables all of these features using the imperative apiRef
. To know more about how to use it, check the API Object section.
deleteFilterItem()
Deletes a GridFilterItem.
Signature:
deleteFilterItem: (item: GridFilterItem) => void
hideFilterPanel()
Hides the filter panel.
Signature:
hideFilterPanel: () => void
setFilterLogicOperator()
Changes the GridLogicOperator used to connect the filters.
Signature:
setFilterLogicOperator: (operator: GridLogicOperator) => void
setFilterModel()
Sets the filter model to the one given by model
.
Signature:
setFilterModel: (model: GridFilterModel, reason?: GridControlledStateReasonLookup['filter']) => void
setQuickFilterValues()
Set the quick filter values ot the one given by values
Signature:
setQuickFilterValues: (values: any[]) => void
showFilterPanel()
Shows the filter panel. If targetColumnField
is given, a filter for this field is also added.
Signature:
showFilterPanel: (targetColumnField?: string) => void
upsertFilterItem()
Updates or inserts a GridFilterItem.
Signature:
upsertFilterItem: (item: GridFilterItem) => void
upsertFilterItems()
Updates or inserts many GridFilterItem.
Signature:
upsertFilterItems: (items: GridFilterItem[]) => void
gridExpandedRowCountSelector
Signature:
gridExpandedRowCountSelector: (apiRef: GridApiRef) => number
// or
gridExpandedRowCountSelector: (state: GridState, instanceId?: number) => number
Example
gridExpandedRowCountSelector(apiRef)
// or
gridExpandedRowCountSelector(state, apiRef.current.instanceId)
gridExpandedSortedRowEntriesSelector
Signature:
gridExpandedSortedRowEntriesSelector: (apiRef: GridApiRef) => { id: GridRowId; model: GridValidRowModel }[]
// or
gridExpandedSortedRowEntriesSelector: (state: GridState, instanceId?: number) => { id: GridRowId; model: GridValidRowModel }[]
Example
gridExpandedSortedRowEntriesSelector(apiRef)
// or
gridExpandedSortedRowEntriesSelector(state, apiRef.current.instanceId)
gridExpandedSortedRowIdsSelector
Signature:
gridExpandedSortedRowIdsSelector: (apiRef: GridApiRef) => GridRowId[]
// or
gridExpandedSortedRowIdsSelector: (state: GridState, instanceId?: number) => GridRowId[]
Example
gridExpandedSortedRowIdsSelector(apiRef)
// or
gridExpandedSortedRowIdsSelector(state, apiRef.current.instanceId)
gridFilterModelSelector
Signature:
gridFilterModelSelector: (apiRef: GridApiRef) => GridFilterModel
// or
gridFilterModelSelector: (state: GridState, instanceId?: number) => GridFilterModel
Example
gridFilterModelSelector(apiRef)
// or
gridFilterModelSelector(state, apiRef.current.instanceId)
gridFilteredSortedRowEntriesSelector
Signature:
gridFilteredSortedRowEntriesSelector: (apiRef: GridApiRef) => { id: GridRowId; model: GridValidRowModel }[]
// or
gridFilteredSortedRowEntriesSelector: (state: GridState, instanceId?: number) => { id: GridRowId; model: GridValidRowModel }[]
Example
gridFilteredSortedRowEntriesSelector(apiRef)
// or
gridFilteredSortedRowEntriesSelector(state, apiRef.current.instanceId)
gridFilteredSortedRowIdsSelector
Signature:
gridFilteredSortedRowIdsSelector: (apiRef: GridApiRef) => GridRowId[]
// or
gridFilteredSortedRowIdsSelector: (state: GridState, instanceId?: number) => GridRowId[]
Example
gridFilteredSortedRowIdsSelector(apiRef)
// or
gridFilteredSortedRowIdsSelector(state, apiRef.current.instanceId)
gridFilteredSortedTopLevelRowEntriesSelector
Signature:
gridFilteredSortedTopLevelRowEntriesSelector: (apiRef: GridApiRef) => { id: GridRowId; model: GridValidRowModel }[]
// or
gridFilteredSortedTopLevelRowEntriesSelector: (state: GridState, instanceId?: number) => { id: GridRowId; model: GridValidRowModel }[]
Example
gridFilteredSortedTopLevelRowEntriesSelector(apiRef)
// or
gridFilteredSortedTopLevelRowEntriesSelector(state, apiRef.current.instanceId)
gridFilteredTopLevelRowCountSelector
Signature:
gridFilteredTopLevelRowCountSelector: (apiRef: GridApiRef) => number
// or
gridFilteredTopLevelRowCountSelector: (state: GridState, instanceId?: number) => number
Example
gridFilteredTopLevelRowCountSelector(apiRef)
// or
gridFilteredTopLevelRowCountSelector(state, apiRef.current.instanceId)
gridQuickFilterValuesSelector
Signature:
gridQuickFilterValuesSelector: (apiRef: GridApiRef) => any[] | undefined
// or
gridQuickFilterValuesSelector: (state: GridState, instanceId?: number) => any[] | undefined
Example
gridQuickFilterValuesSelector(apiRef)
// or
gridQuickFilterValuesSelector(state, apiRef.current.instanceId)
More information about the selectors and how to use them on the dedicated page