Global Filtering (Search) Feature Guide
Material React Table has a powerful built-in global filtering (search) feature that uses a fuzzy matching algorithm and ranks/sorts the results based on how closely rows match the search query. In this guide, we'll cover how to use, customize, or disable the global filter and search features to fit your needs.
Relevant Props
# | Prop Name 2 | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
|
| MRT Column Filtering Docs | ||
2 |
|
| MRT Global Filtering Docs | ||
3 |
|
| MRT Global Filtering Docs | ||
4 |
|
| MRT Global Filtering Docs | ||
5 |
| ||||
6 |
| ||||
7 |
| ||||
8 |
| TanStack Table Filters Docs | |||
9 |
| Material UI TextField Props | |||
10 |
| TanStack Table Filters Docs | |||
11 |
| TanStack Table Filters Docs | |||
12 |
| ||||
13 |
| ||||
14 |
| ||||
Relevant Column Options
# | Column Option 2 | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| MRT Column Filtering Docs | |||
2 |
| ||||
Relevant State Options
# | State Option | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| TanStack Table Filtering Docs | |||
2 |
| ||||
3 |
|
| |||
Disable Global Filtering
You can either disable the global filter feature entirely or disable it for specific columns.
Disable Global Filtering per Column
If you simply want to not include a column as one of the columns that the global filter scans through during filtering, you can set the enableGlobalFilter
option to false
for that column.
const columns = [{accessorKey: 'id',header: 'Id',enableGlobalFilter: false, // do not scan this column during global filtering},{accessorKey: 'name',header: 'Name',},];
Disable Global Filter Feature
You can disable the global filtering feature and hide the search icon by setting the enableGlobalFilter
prop to false
.
<MaterialReactTablecolumns={columns}data={data}enableGlobalFilter={false} //disable search feature/>
Filter Match Highlighting
New in v1.6
Filter match highlighting is a new featured enabled by default that will highlight text in the table body cells that matches the current search query with a shade of the theme.palette.warning.main
color.
If you are using a custom Cell
render override for a column, you will need to use the renderedCellValue
prop instead of cell.getValue()
to preserve the filter match highlighting.
const columns = [{accessorKey: 'name',header: 'Name',Cell: ({ renderedCellValue }) => <span>{renderedCellValue}</span>, // use renderedCellValue instead of cell.getValue()},];
Disable Filter Match Highlighting
Filter match highlighting can be disabled by setting the enableFilterMatchHighlighting
prop to false
.
<MaterialReactTablecolumns={columns}data={data}enableFilterMatchHighlighting={false}/>
Client-Side Global Filtering
Client-side filtering (and global filtering) is enabled by default. This means that the search box will scan through all columns and try to find matches for the search term.
Global Filter Function
You can use any of the built-in filterFns
or any of the custom filter functions that you have defined in the filterFns
prop, just like you would with the column filters.
<MaterialReactTablecolumns={columns}data={data}globalFilterFn="contains" //turn off fuzzy matching and use simple contains filter function/>
Or a custom filter function:
<MaterialReactTablecolumns={columns}data={data}filterFns={{myCustomFilterFn: (row, id, filterValue) =>row.getValue(id).startsWith(filterValue),}}globalFilterFn="myCustomFilterFn" //set the global filter function to myCustomFilterFn/>
The default global filter function is set to fuzzy
, which is a filtering algorithm based on the popular match-sorter
library from Kent C. Dodds, though you can change the global filter function by setting the globalFilterFn
prop.
Ranked Results
If you keep the default fuzzy
filterFn option as the global filter function, you get an extra ranked results feature enabled by default. This means that when a user searches with the search box, the results will be sorted by the closest match first instead of the order the data was defined in.
The ranked results feature will disable itself automatically if a sort direction is applied to a column, if any sub-rows are expanded, or if any of the manual
props are set to true
.
If you do not want ranked results to be enabled at all, but you still want fuzzy matching, you can set the enableGlobalFilterRankedResults
prop to false
.
<MaterialReactTablecolumns={columns}data={data}enableGlobalFilterRankedResults={false} //preserve the order of the data when fuzzy match searching/>
Global Filter Modes
Similar to the column filter modes, you can enable the user to be able to choose between multiple different filter modes for the global filter with the enableGlobalFilterModes
prop. You can then customize which filter modes are available in the drop-down by setting the globalFilterModeOptions
prop or by rendering your own custom menu items with the renderGlobalFilterModeMenuItems
prop.
<MaterialReactTablecolumns={columns}data={data}enableGlobalFilterModes //enable the user to choose between multiple search filter modesglobalFilterModeOptions={['fuzzy', 'startsWith']} //only allow the user to choose between fuzzy and startsWith filter modes/>
Show Search Field by Default
Additionally, if you want to show the search text box by default and not hide it behind the search icon, you can set the showGlobalFilter
state to true
in the initialState
.
Manual Server-Side Global 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 globalFilter
state yourself like in the example below (can work in conjuntion with manual column filtering).
// You can manage and have control over the columnFilters state yourselfconst [globalFilter, setGlobalFilter] = 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]);};}, [globalFilter]);return (<MaterialReactTablecolumns={columns}data={data} // this will already be filtered on the servermanualFiltering //turn off client-side filteringonGlobalFilterChange={setGlobalFilter} //hoist internal global state to your statestate={{ globalFilter }} //pass in your own managed globalFilter 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, { useEffect, useMemo, useState } from 'react';2import {3 MaterialReactTable,4 type MRT_ColumnDef,5 type MRT_ColumnFiltersState,6 type MRT_PaginationState,7 type MRT_SortingState,8} from 'material-react-table';910type UserApiResponse = {11 data: Array<User>;12 meta: {13 totalRowCount: number;14 };15};1617type User = {18 firstName: string;19 lastName: string;20 address: string;21 state: string;22 phoneNumber: string;23};2425const Example = () => {26 //data and fetching state27 const [data, setData] = useState<User[]>([]);28 const [isError, setIsError] = useState(false);29 const [isLoading, setIsLoading] = useState(false);30 const [isRefetching, setIsRefetching] = useState(false);31 const [rowCount, setRowCount] = useState(0);3233 //table state34 const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(35 [],36 );37 const [globalFilter, setGlobalFilter] = useState('');38 const [sorting, setSorting] = useState<MRT_SortingState>([]);39 const [pagination, setPagination] = useState<MRT_PaginationState>({40 pageIndex: 0,41 pageSize: 10,42 });4344 //if you want to avoid useEffect, look at the React Query example instead45 useEffect(() => {46 const fetchData = async () => {47 if (!data.length) {48 setIsLoading(true);49 } else {50 setIsRefetching(true);51 }5253 const url = new URL(54 '/api/data',55 process.env.NODE_ENV === 'production'56 ? 'https://www.material-react-table.com'57 : 'http://localhost:3000',58 );59 url.searchParams.set(60 'start',61 `${pagination.pageIndex * pagination.pageSize}`,62 );63 url.searchParams.set('size', `${pagination.pageSize}`);64 url.searchParams.set('filters', JSON.stringify(columnFilters ?? []));65 url.searchParams.set('globalFilter', globalFilter ?? '');66 url.searchParams.set('sorting', JSON.stringify(sorting ?? []));6768 try {69 const response = await fetch(url.href);70 const json = (await response.json()) as UserApiResponse;71 setData(json.data);72 setRowCount(json.meta.totalRowCount);73 } catch (error) {74 setIsError(true);75 console.error(error);76 return;77 }78 setIsError(false);79 setIsLoading(false);80 setIsRefetching(false);81 };82 fetchData();83 // eslint-disable-next-line react-hooks/exhaustive-deps84 }, [85 columnFilters,86 globalFilter,87 pagination.pageIndex,88 pagination.pageSize,89 sorting,90 ]);9192 const columns = useMemo<MRT_ColumnDef<User>[]>(93 () => [94 {95 accessorKey: 'firstName',96 header: 'First Name',97 },98 //column definitions...116 ],117 [],118 );119120 return (121 <MaterialReactTable122 columns={columns}123 data={data}124 enableRowSelection125 getRowId={(row) => row.phoneNumber}126 initialState={{ showColumnFilters: true }}127 manualFiltering128 manualPagination129 manualSorting130 muiToolbarAlertBannerProps={131 isError132 ? {133 color: 'error',134 children: 'Error loading data',135 }136 : undefined137 }138 onColumnFiltersChange={setColumnFilters}139 onGlobalFilterChange={setGlobalFilter}140 onPaginationChange={setPagination}141 onSortingChange={setSorting}142 rowCount={rowCount}143 state={{144 columnFilters,145 globalFilter,146 isLoading,147 pagination,148 showAlertBanner: isError,149 showProgressBars: isRefetching,150 sorting,151 }}152 />153 );154};155156export default Example;157
Customize Global Filter Position
You can customize the position of the global filter (search box) in the top toolbar by setting the positionGlobalFilter
prop to left
or right
. It is shown on the right by default.
<MaterialReactTablecolumns={columns}data={data}positionGlobalFilter="left" //show the global filter on the left side of the top toolbarinitialState={{showGlobalFilter: true, //show the global filter by default}}/>
Customize the Search Text Field
You can customize the search text field by passing in props to the muiSearchTextFieldProps
prop. This is useful if you want to customize the placeholder text, add styles, or any other text field props.
<MaterialReactTablecolumns={columns}data={data}muiSearchTextFieldProps={{placeholder: 'Search all users',sx: { minWidth: '300px' },variant: 'outlined',}}/>
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, { useMemo } from 'react';2import { MaterialReactTable, type MRT_ColumnDef } from 'material-react-table';3import { data, type Person } from './makeData';45const Example = () => {6 const columns = useMemo<MRT_ColumnDef<Person>[]>(7 //column definitions...32 );3334 return (35 <MaterialReactTable36 columns={columns}37 data={data}38 enableGlobalFilterModes39 initialState={{40 showGlobalFilter: true,41 }}42 positionGlobalFilter="left"43 muiSearchTextFieldProps={{44 placeholder: `Search ${data.length} rows`,45 sx: { minWidth: '300px' },46 variant: 'outlined',47 }}48 />49 );50};5152export default Example;53
View Extra Storybook Examples