Column Filtering Feature Guide
Filtering is one of the most powerful features of Material React Table and is enabled by default. There is a lot of flexibility and customization available here, whether you want to customize the powerful client-side filtering already built in, or implement your own server-side filtering, Material React Table has got you covered.
Relevant Props
# | Prop Name | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| ||||
No Description Provided... Yet... | |||||
2 |
|
| |||
No Description Provided... Yet... | |||||
3 |
|
| |||
No Description Provided... Yet... | |||||
4 |
|
| |||
No Description Provided... Yet... | |||||
5 |
| TanStack Table Filters Docs | |||
This option allows you to define custom filter functions that can be referenced in a column's filterFn option by their key | |||||
6 |
| ||||
No Description Provided... Yet... | |||||
7 | |||||
No Description Provided... Yet... | |||||
8 | |||||
No Description Provided... Yet... | |||||
9 | |||||
No Description Provided... Yet... | |||||
10 | |||||
No Description Provided... Yet... | |||||
11 | |||||
No Description Provided... Yet... | |||||
12 | |||||
No Description Provided... Yet... | |||||
13 | |||||
No Description Provided... Yet... |
Relevant Column Options
# | Column Option | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| MRT Column Filtering Docs | |||
Define a custom filter component in a column. | |||||
2 |
| ||||
No Description Provided... Yet... | |||||
3 |
| MRT Column Filtering Docs | |||
Enable or disable column filtering for this column. Filter will not be shown if disabled. | |||||
4 |
| MRT Column Filtering Docs | |||
Enable column filtering modes for this column. | |||||
5 |
|
| |||
No Description Provided... Yet... | |||||
6 |
| ||||
No Description Provided... Yet... | |||||
7 |
|
| |||
Specify whether the filter should be a text input or a select input, or other type of pre-built input. | |||||
8 |
| Material UI TextField Props | |||
No Description Provided... Yet... | |||||
9 | |||||
No Description Provided... Yet... |
Relevant State Options
# | State Option | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| ||||
No Description Provided... Yet... | |||||
2 |
|
| TanStack Table Filters Docs | ||
No Description Provided... Yet... | |||||
3 |
|
| |||
No Description Provided... Yet... |
Disable Filtering Features
Various subsets of filtering features can be disabled. If you want to disable filtering completely, you can set the enableColumnFilters
prop to false
, to remove all filters from each column. Alternatively, enableColumnFilter
can be set to false
for individual columns.
enableFilters
can be set to false
to disable both column filters and the global search filter.
ID | First Name | Middle Name | Last Name |
---|---|---|---|
1 | Hugh | Jay | Mungus |
2 | Leroy | Leroy | Jenkins |
1import React, { FC, useMemo } from 'react';2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';34const Example: FC = () => {5 const columns = useMemo(6 () =>7 [8 {9 accessorKey: 'id',10 enableColumnFilter: false, // could disable just this column's filter11 header: 'ID',12 },13 //column definitions...27 ] as MRT_ColumnDef<typeof data[0]>[],28 [],29 );3031 const data = useMemo(32 //data definitions...49 );5051 return (52 <MaterialReactTable53 columns={columns}54 data={data}55 enableColumnFilters={false} //disable all column filters56 />57 );58};5960export default Example;61
Filter Variants
Material React Table has some built in filter variants for advanced filtering. These can be specified on a per-column basis using the filterVariant
option. The following variants are available:
'text'
- shows the default text field'select'
- shows a select dropdown with the options specified infilterSelectOptions
'multi-select'
- shows a select dropdown with the options specified infilterSelectOptions
and allows multiple selections with checkboxes'range
- shows min and max text fields for filtering a range of values'checkbox'
- shows a checkbox for filtering by'true'
or'false'
values (Strings)
Account Status | Name | Age | City Filter by City | State Filter by State |
---|---|---|---|---|
Active | Tanner Linsley | 42 | San Francisco | California |
Active | Kevin Vandy | 51 | Richmond | Virginia |
Inactive | John Doe | 27 | Riverside | South Carolina |
Active | Jane Doe | 32 | San Francisco | California |
Inactive | John Smith | 42 | Los Angeles | California |
Active | Jane Smith | 51 | Blacksburg | Virginia |
Inactive | Samuel Jackson | 27 | New York | New York |
1import React, { FC, useMemo } from 'react';2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';3import { citiesList, data, Person, usStateList } from './makeData';45const Example: FC = () => {6 const columns = useMemo<MRT_ColumnDef<Person>[]>(7 () => [8 {9 header: 'Account Status',10 accessorFn: (originalRow) => (originalRow.isActive ? 'true' : 'false'), //must be strings11 id: 'isActive',12 filterVariant: 'checkbox',13 Cell: ({ cell }) =>14 cell.getValue() === 'true' ? 'Active' : 'Inactive',15 size: 220,16 },17 {18 accessorKey: 'name',19 header: 'Name',20 filterVariant: 'text', // default21 },22 {23 accessorKey: 'age',24 header: 'Age',25 filterVariant: 'range',26 filterFn: 'betweenInclusive', // use betweenInclusive instead of between27 },28 {29 accessorKey: 'city',30 header: 'City',31 filterVariant: 'select',32 filterSelectOptions: citiesList,33 },34 {35 accessorKey: 'state',36 header: 'State',37 filterVariant: 'multi-select',38 filterSelectOptions: usStateList,39 },40 ],41 [],42 );4344 return (45 <MaterialReactTable46 columns={columns}47 data={data}48 initialState={{ showColumnFilters: true }}49 />50 );51};5253export default Example;54
Custom Filter Functions
You can specify either a pre-built filterFn that comes with Material React Table, or pass in your own custom filter functions.
Custom Filter Functions Per Column
By default, Material React Table uses a fuzzy
filtering algorithm based on the popular match-sorter
library from Kent C. Dodds. However, Material React Table also comes with numerous other filter functions that you can specify per column in the filterFn
column options.
Pre-built MRT Filter Functions
Prebuilt filter functions from Material React table include
between
,betweenInclusive
,contains
,empty
,endsWith
,equals
,fuzzy
,greaterThan
,greaterThanOrEqualTo
,lessThan
,lessThanOrEqualTo
,notEmpty
,notEquals
, andstartsWith
. View these algorithms here
Pre-built TanStack Table Filter Functions
Prebuilt filter functions from TanStack Table include
includesString
,includesStringSensitive
,equalsString
,equalsStringSensitive
,arrIncludes
,arrIncludesAll
,arrIncludesSome
,weakEquals
, andinNumberRange
. View more information about these algorithms in the TanStack Table Filter docs.
You can specify either a prebuilt filter function, from Material React Table or TanStack Table, or you can even specify your own custom filter function in the filterFn
column option.
const columns = [{accessorKey: 'firstName',header: 'First Name',// using a prebuilt filter function from Material React TablefilterFn: 'startsWith',},{accessorKey: 'middleName',header: 'Middle Name',// using a prebuilt filter function from TanStack TablefilterFn: 'includesStringSensitive',},{accessorKey: 'lastName',header: 'Last Name',// custom filter functionfilterFn: (row, id, filterValue) =>row.getValue(id).startsWith(filterValue),},];
If you provide a custom filter function, it must have the following signature:
(row: Row<TData>, id: string, filterValue: string | number) => boolean;
This function will be used to filter 1 row at a time, and should return a boolean
indicating whether or not that row passes the filter.
Add Custom Filter Functions
You can add custom filter functions to the filterFns
prop. These will be available to all columns to use. The filterFn
prop on a column will override any filter function with the same name in the filterFns
prop.
const columns = [{accessorKey: 'name',header: 'Name',filterFn: 'customFilterFn',},];return (<MaterialReactTabledata={data}columns={columns}filterFns={{customFilterFn: (row, id, filterValue) => {return row.customField === value;},}}/>);
Filter Modes
Enable Column Filter Modes (Filter Switching)
If you want to let the user switch between multiple different filter modes from a dropdown menu on the Filter Textfield, you can enable that with the enableColumnFilterModes
prop or column option. This will enable the filter icon in the filter text field to open a dropdown menu with the available filter modes when clicked.
<MaterialReactTable columns={columns} data={data} enableColumnFilterModes />
Customize Filter Modes
You can narrow down the available filter mode options by setting the columnFilterModeOptions
prop, or a column specific columnFilterModeOptions
option.
const columns = [{accessorKey: 'firstName',header: 'First Name',columnFilterModeOptions: ['fuzzy', 'contains', 'startsWith'],},{accessorKey: 'age',header: 'Age',columnFilterModeOptions: ['between', 'lessThan', 'greaterThan'],},}]
Render Custom Filter Mode Menu
You can also render custom menu items in the filter mode dropdown menu by setting the renderColumnFilterModeMenuItems
prop or column option. This option is a function that takes in the column and returns an array of MenuItem
components. This is useful if you want to add custom filter modes that are not included in Material React Table, or if you just want to render the menu in your own custom way
const columns = [{accessorKey: 'firstName',header: 'First Name',renderColumnFilterModeMenuItems: ({ column, onSelectFilterMode }) => [<MenuItemkey="startsWith"onClick={() => onSelectFilterMode('startsWith')}>Start With</MenuItem>,<MenuItemkey="endsWith"onClick={() => onSelectFilterMode('yourCustomFilterFn')}>Your Custom Filter Fn</MenuItem>,],},];return (<MaterialReactTablecolumns={columns}data={data}enableColumnFilterModes// renderColumnFilterModeMenuItems could go here if you want to apply to all columns/>);
ID | First Name | Middle Name | Last Name | Age |
---|---|---|---|---|
1 | Hugh | Jay | Mungus | 42 |
2 | Leroy | Leroy | Jenkins | 51 |
3 | Candice | Denise | Nutella | 27 |
4 | Micah | Henry | Johnson | 32 |
1import React, { FC, useMemo } from 'react';2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';3import { MenuItem } from '@mui/material';4import { data, Person } from './makeData';56const Example: FC = () => {7 const columns = useMemo<MRT_ColumnDef<Person>[]>(8 () => [9 {10 accessorKey: 'id',11 enableColumnFilterModes: false, //disable changing filter mode for this column12 filterFn: 'equals', //set filter mode to equals13 header: 'ID',14 },15 {16 accessorKey: 'firstName', //normal, all filter modes are enabled17 header: 'First Name',18 },19 {20 accessorKey: 'middleName',21 enableColumnFilterModes: false, //disable changing filter mode for this column22 filterFn: 'startsWith', //even though changing the mode is disabled, you can still set the default filter mode23 header: 'Middle Name',24 },25 {26 accessorKey: 'lastName',27 header: 'Last Name',28 //if you don't want to use the default filter modes, you can provide your own and render your own menu29 renderColumnFilterModeMenuItems: ({ onSelectFilterMode }) => [30 <MenuItem key="0" onClick={() => onSelectFilterMode('contains')}>31 <div>Contains</div>32 </MenuItem>,33 <MenuItem34 key="1"35 onClick={() => onSelectFilterMode('customFilterFn')}36 >37 <div>Custom Filter Fn</div>38 </MenuItem>,39 ],40 },41 {42 accessorKey: 'age',43 columnFilterModeOptions: ['between', 'greaterThan', 'lessThan'], //only allow these filter modes44 filterFn: 'between',45 header: 'Age',46 },47 ],48 [],49 );5051 return (52 <MaterialReactTable53 columns={columns}54 data={data}55 enableColumnFilterModes //enable changing filter mode for all columns unless explicitly disabled in a column def56 initialState={{ showColumnFilters: true }} //show filters by default57 filterFns={{58 customFilterFn: (row, id, filterValue) => {59 return row.getValue(id) === filterValue;60 },61 }}62 localization={63 {64 filterCustomFilterFn: 'Custom Filter Fn',65 } as any66 }67 />68 );69};7071export default Example;72
Manual Server-Side Filtering
A very common use case when you have a lot of data is to filter the data on the server, instead of client-side. In this case you will want to set the manualFiltering
prop to true
and manage the columnFilters
state yourself like so.
// You can manage and have control over the columnFilters state yourselfconst [columnFilters, setColumnFilters] = useState([]);const [data, setData] = useState([]); //data will get updated after re-fetchinguseEffect(() => {const fetchData = async () => {// send api requests when columnFilters state changesconst filteredData = await fetch();setData([...filteredData]);};}, [columnFilters]);return (<MaterialReactTablecolumns={columns}data={data} // this will already be filtered on the servermanualFiltering //turn off client-side filteringonColumnFiltersChange={setColumnFilters} //hoist internal columnFilters state to your statestate={{ columnFilters }} //pass in your own managed columnFilters state/>);
Specifying
manualFiltering
turns off all client-side filtering, and assumes that thedata
you pass to<MaterialReactTable />
is already filtered.
Here is the full Remote Data example showing off server-side filtering, pagination, and sorting.
First Name | Last Name | Address | State | Phone Number | |
---|---|---|---|---|---|
No records to display |
1import React, { FC, useEffect, useMemo, useState } from 'react';2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';3import type {4 ColumnFiltersState,5 PaginationState,6 SortingState,7} from '@tanstack/react-table';89type UserApiResponse = {10 data: Array<User>;11 meta: {12 totalRowCount: number;13 };14};1516type User = {17 firstName: string;18 lastName: string;19 address: string;20 state: string;21 phoneNumber: string;22};2324const Example: FC = () => {25 const [data, setData] = useState<User[]>([]);26 const [isError, setIsError] = useState(false);27 const [isLoading, setIsLoading] = useState(false);28 const [isRefetching, setIsRefetching] = useState(false);29 const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);30 const [globalFilter, setGlobalFilter] = useState('');31 const [sorting, setSorting] = useState<SortingState>([]);32 const [pagination, setPagination] = useState<PaginationState>({33 pageIndex: 0,34 pageSize: 10,35 });36 const [rowCount, setRowCount] = useState(0);3738 //if you want to avoid useEffect, look at the React Query example instead39 useEffect(() => {40 const fetchData = async () => {41 if (!data.length) {42 setIsLoading(true);43 } else {44 setIsRefetching(true);45 }4647 const url = new URL('/api/data', 'https://www.material-react-table.com');48 url.searchParams.set(49 'start',50 `${pagination.pageIndex * pagination.pageSize}`,51 );52 url.searchParams.set('size', `${pagination.pageSize}`);53 url.searchParams.set('filters', JSON.stringify(columnFilters ?? []));54 url.searchParams.set('globalFilter', globalFilter ?? '');55 url.searchParams.set('sorting', JSON.stringify(sorting ?? []));5657 try {58 const response = await fetch(url.href);59 const json = (await response.json()) as UserApiResponse;60 setData(json.data);61 setRowCount(json.meta.totalRowCount);62 } catch (error) {63 setIsError(true);64 console.error(error);65 return;66 }67 setIsError(false);68 setIsLoading(false);69 setIsRefetching(false);70 };71 fetchData();72 // eslint-disable-next-line react-hooks/exhaustive-deps73 }, [74 columnFilters,75 globalFilter,76 pagination.pageIndex,77 pagination.pageSize,78 sorting,79 ]);8081 const columns = useMemo<MRT_ColumnDef<User>[]>(82 () => [83 {84 accessorKey: 'firstName',85 header: 'First Name',86 },87 //column definitions...105 ],106 [],107 );108109 return (110 <MaterialReactTable111 columns={columns}112 data={data}113 enableRowSelection114 getRowId={(row) => row.phoneNumber}115 initialState={{ showColumnFilters: true }}116 manualFiltering117 manualPagination118 manualSorting119 muiToolbarAlertBannerProps={120 isError121 ? {122 color: 'error',123 children: 'Error loading data',124 }125 : undefined126 }127 onColumnFiltersChange={setColumnFilters}128 onGlobalFilterChange={setGlobalFilter}129 onPaginationChange={setPagination}130 onSortingChange={setSorting}131 rowCount={rowCount}132 state={{133 columnFilters,134 globalFilter,135 isLoading,136 pagination,137 showAlertBanner: isError,138 showProgressBars: isRefetching,139 sorting,140 }}141 />142 );143};144145export default Example;146
Customize MUI Filter components
You can customize the MUI filter components by setting the muiTableHeadCellFilterTextFieldProps
prop or column option.
You can also turn a filter textfield into a select dropdown by setting the filterSelectOptions
prop or column option.
ID | First Name | Last Name | Gender Filter by Gender | Age |
---|---|---|---|---|
1 | Hugh | Mungus | Male | 42 |
2 | Leroy | Jenkins | Male | 51 |
3 | Candice | Nutella | Female | 27 |
4 | Micah | Johnson | Other | 32 |
1import React, { FC, useMemo } from 'react';2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';34export type Person = {5 id: number;6 firstName: string;7 lastName: string;8 gender: string;9 age: number;10};1112const Example: FC = () => {13 const columns = useMemo<MRT_ColumnDef<Person>[]>(14 () => [15 {16 accessorKey: 'id',17 header: 'ID',18 muiTableHeadCellFilterTextFieldProps: { placeholder: 'ID' },19 },20 {21 accessorKey: 'firstName',22 header: 'First Name',23 },24 {25 accessorKey: 'lastName',26 header: 'Last Name',27 },28 {29 accessorKey: 'gender',30 header: 'Gender',31 filterFn: 'equals',32 filterSelectOptions: [33 { text: 'Male', value: 'Male' },34 { text: 'Female', value: 'Female' },35 { text: 'Other', value: 'Other' },36 ],37 filterVariant: 'select',38 },39 {40 accessorKey: 'age',41 header: 'Age',42 filterVariant: 'range',43 },44 ],45 [],46 );4748 const data = useMemo<Person[]>(49 //data definitions...82 );8384 return (85 <MaterialReactTable86 columns={columns}87 data={data}88 initialState={{ showColumnFilters: true }} //show filters by default89 muiTableHeadCellFilterTextFieldProps={{90 sx: { m: '0.5rem 0', width: '100%' },91 variant: 'outlined',92 }}93 />94 );95};9697export default Example;98
Custom Filter Components
If you need custom filter components that are much more complex than textboxes and dropdowns, you can create and pass in your own filter components using the Filter
column option.
View Extra Storybook Examples