MRT logoMaterial React Table

On This Page

    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

    1
    Array<MRT_FilterOption | string> | null
    MRT Column Filtering Docs
    2
    boolean
    false
    MRT Column Filtering Docs
    3
    boolean
    true
    MRT Column Filtering Docs
    4
    boolean
    true
    MRT Column Filtering Docs
    5
    boolean
    true
    TanStack Filters Docs
    6
    Record<string, FilterFn>
    TanStack Table Filters Docs
    7
    boolean
    false
    TanStack Filtering Docs
    8
    () => Map<any, number>
    TanStack Table Filters Docs
    9
    () => RowModel<TData>
    TanStack Table Filters Docs
    10
    () => Map<any, number>
    TanStack Table Filters Docs
    11
    () => RowModel<TData>
    TanStack Table Filters Docs
    12
    boolean
    TanStack Table Filters Docs
    13
    number
    100
    TanStack Table Filtering Docs
    14
    TextFieldProps | ({ table, column, rangeFilterIndex}) => TextFieldProps
    Material UI TextField Props
    15
    OnChangeFn<{ [key: string]: MRT_FilterOption }>
    16
    OnChangeFn<ColumnFiltersState>
    TanStack Table Filter Docs
    17
    OnChangeFn<boolean>
    18
    ({ column, internalFilterOptions, onSelectFilterMode, table }) => ReactNode[]

    Relevant Column Options

    1
    ({ column, header, table }) => ReactNode
    MRT Column Filtering Docs
    2
    Array<string>
    3
    boolean
    MRT Column Filtering Docs
    4
    boolean
    MRT Column Filtering Docs
    5
    boolean
    MRT Column Filtering Docs
    6
    MRT_FilterFn
    fuzzy
    7
    Array<string | { text: string; value: string }>
    8
    'text' | 'select' | 'multi-select' | 'range'
    text
    9
    TextFieldProps | ({ column, rangeFilterIndex, table }) => TextFieldProps
    Material UI TextField Props
    10

    Relevant State Options

    1
    { [key: string]: MRT_FilterFn }
    2
    Array<{id: string, value: unknown}>
    {}
    TanStack Table Filters Docs
    3
    boolean
    false

    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.


    Demo

    Open StackblitzOpen Code SandboxOpen on GitHub
    1HughJayMungus
    2LeroyLeroyJenkins

    Rows per page

    1-2 of 2

    Source Code

    1import React, { useMemo } from 'react';
    2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';
    3
    4const Example = () => {
    5 const columns = useMemo(
    6 () =>
    7 [
    8 {
    9 accessorKey: 'id',
    10 enableColumnFilter: false, // could disable just this column's filter
    11 header: 'ID',
    12 },
    13 //column definitions...
    27 ] as MRT_ColumnDef<(typeof data)[0]>[],
    28 [],
    29 );
    30
    31 const data = useMemo(
    32 //data definitions...
    49 );
    50
    51 return (
    52 <MaterialReactTable
    53 columns={columns}
    54 data={data}
    55 enableColumnFilters={false} //disable all column filters
    56 />
    57 );
    58};
    59
    60export default Example;
    61

    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 filter query with a shade of the theme.palette.warning.main color.

    Filter Match Highlighting will only work on columns with the default text filter variant. Also, if you are using a custom Cell render override for a column, you will need to use the renderedCellValue prop instead of cell.getValue() in order 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

    This feature can be disabled by setting the enableFilterMatchHighlighting prop to false.

    <MaterialReactTable
    columns={columns}
    data={data}
    enableFilterMatchHighlighting={false}
    />

    Filter Variants

    Material React Table has several 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 in filterSelectOptions

    • 'multi-select' - shows a select dropdown with the options specified in filterSelectOptions 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)


    Demo

    ActiveTanner Linsley42San FranciscoCalifornia
    ActiveKevin Vandy51RichmondVirginia
    InactiveJohn Doe27RiversideSouth Carolina
    ActiveJane Doe32San FranciscoCalifornia
    InactiveJohn Smith42Los AngelesCalifornia
    ActiveJane Smith51BlacksburgVirginia
    InactiveSamuel Jackson27New YorkNew York

    Rows per page

    1-7 of 7

    Source Code

    1import React, { useMemo } from 'react';
    2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';
    3import { citiesList, data, Person, usStateList } from './makeData';
    4
    5const Example = () => {
    6 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    7 () => [
    8 {
    9 header: 'Account Status',
    10 accessorFn: (originalRow) => (originalRow.isActive ? 'true' : 'false'), //must be strings
    11 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', // default
    21 },
    22 {
    23 accessorKey: 'age',
    24 header: 'Age',
    25 filterVariant: 'range',
    26 filterFn: 'betweenInclusive', // use betweenInclusive instead of between
    27 },
    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 );
    43
    44 return (
    45 <MaterialReactTable
    46 columns={columns}
    47 data={data}
    48 initialState={{ showColumnFilters: true }}
    49 />
    50 );
    51};
    52
    53export 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

    Pre-built filter functions from Material React Table include between, betweenInclusive, contains, empty, endsWith, equals, fuzzy, greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo, notEmpty, notEquals, and startsWith. View these algorithms here

    Pre-built TanStack Table Filter Functions

    Pre-built filter functions from TanStack Table include includesString, includesStringSensitive, equalsString, equalsStringSensitive, arrIncludes, arrIncludesAll, arrIncludesSome, weakEquals, and inNumberRange. View more information about these algorithms in the TanStack Table Filter docs.

    You can specify either a pre-built 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 Table
    filterFn: 'startsWith',
    },
    {
    accessorKey: 'middleName',
    header: 'Middle Name',
    // using a prebuilt filter function from TanStack Table
    filterFn: 'includesStringSensitive',
    },
    {
    accessorKey: 'lastName',
    header: 'Last Name',
    // custom filter function
    filterFn: (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 (
    <MaterialReactTable
    data={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 drop-down 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 drop-down 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 drop-down 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 }) => [
    <MenuItem
    key="startsWith"
    onClick={() => onSelectFilterMode('startsWith')}
    >
    Start With
    </MenuItem>,
    <MenuItem
    key="endsWith"
    onClick={() => onSelectFilterMode('yourCustomFilterFn')}
    >
    Your Custom Filter Fn
    </MenuItem>,
    ],
    },
    ];
    return (
    <MaterialReactTable
    columns={columns}
    data={data}
    enableColumnFilterModes
    // renderColumnFilterModeMenuItems could go here if you want to apply to all columns
    />
    );

    Demo

    1HughJayMungus42
    2LeroyLeroyJenkins51
    3CandiceDeniseNutella27
    4MicahHenryJohnson32

    Rows per page

    1-4 of 4

    Source Code

    1import React, { useMemo } from 'react';
    2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';
    3import { MenuItem } from '@mui/material';
    4import { data, Person } from './makeData';
    5
    6const Example = () => {
    7 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    8 () => [
    9 {
    10 accessorKey: 'id',
    11 enableColumnFilterModes: false, //disable changing filter mode for this column
    12 filterFn: 'equals', //set filter mode to equals
    13 header: 'ID',
    14 },
    15 {
    16 accessorKey: 'firstName', //normal, all filter modes are enabled
    17 header: 'First Name',
    18 },
    19 {
    20 accessorKey: 'middleName',
    21 enableColumnFilterModes: false, //disable changing filter mode for this column
    22 filterFn: 'startsWith', //even though changing the mode is disabled, you can still set the default filter mode
    23 header: 'Middle Name',
    24 },
    25 {
    26 accessorKey: 'lastName',
    27 header: 'Last Name',
    28 //if you do not want to use the default filter modes, you can provide your own and render your own menu
    29 renderColumnFilterModeMenuItems: ({ onSelectFilterMode }) => [
    30 <MenuItem key="0" onClick={() => onSelectFilterMode('contains')}>
    31 <div>Contains</div>
    32 </MenuItem>,
    33 <MenuItem
    34 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 modes
    44 filterFn: 'between',
    45 header: 'Age',
    46 },
    47 ],
    48 [],
    49 );
    50
    51 return (
    52 <MaterialReactTable
    53 columns={columns}
    54 data={data}
    55 enableColumnFilterModes //enable changing filter mode for all columns unless explicitly disabled in a column def
    56 initialState={{ showColumnFilters: true }} //show filters by default
    57 filterFns={{
    58 customFilterFn: (row, id, filterValue) => {
    59 return row.getValue(id) === filterValue;
    60 },
    61 }}
    62 localization={
    63 {
    64 filterCustomFilterFn: 'Custom Filter Fn',
    65 } as any
    66 }
    67 />
    68 );
    69};
    70
    71export default Example;
    72

    Expanded Leaf Row Filtering Options

    If you are using the filtering features along-side either the grouping or expanding features, then there are a few behaviors and customizations you should be aware of.

    Check out the Expanded Leaf Row Filtering Behavior docs to learn more about the filterFromLeafRows and maxLeafRowFilterDepth props.

    Manual Server-Side Column 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 (can work in conjunction with manual global filtering).

    // You can manage and have control over the columnFilters state yourself
    const [columnFilters, setColumnFilters] = useState([]);
    const [data, setData] = useState([]); //data will get updated after re-fetching
    useEffect(() => {
    const fetchData = async () => {
    // send api requests when columnFilters state changes
    const filteredData = await fetch();
    setData([...filteredData]);
    };
    }, [columnFilters]);
    return (
    <MaterialReactTable
    columns={columns}
    data={data} // this will already be filtered on the server
    manualFiltering //turn off client-side filtering
    onColumnFiltersChange={setColumnFilters} //hoist internal columnFilters state to your state
    state={{ columnFilters }} //pass in your own managed columnFilters state
    />
    );

    Specifying manualFiltering turns off all client-side filtering and assumes that the data you pass to <MaterialReactTable /> is already filtered.

    Here is the full Remote Data example featuring server-side filtering, pagination, and sorting.


    Demo

    No records to display

    Rows per page

    0-0 of 0

    Source Code

    1import React, { useEffect, useMemo, useState } from 'react';
    2import MaterialReactTable, {
    3 MRT_ColumnDef,
    4 MRT_ColumnFiltersState,
    5 MRT_PaginationState,
    6 MRT_SortingState,
    7} from 'material-react-table';
    8
    9type UserApiResponse = {
    10 data: Array<User>;
    11 meta: {
    12 totalRowCount: number;
    13 };
    14};
    15
    16type User = {
    17 firstName: string;
    18 lastName: string;
    19 address: string;
    20 state: string;
    21 phoneNumber: string;
    22};
    23
    24const Example = () => {
    25 //data and fetching state
    26 const [data, setData] = useState<User[]>([]);
    27 const [isError, setIsError] = useState(false);
    28 const [isLoading, setIsLoading] = useState(false);
    29 const [isRefetching, setIsRefetching] = useState(false);
    30 const [rowCount, setRowCount] = useState(0);
    31
    32 //table state
    33 const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
    34 [],
    35 );
    36 const [globalFilter, setGlobalFilter] = useState('');
    37 const [sorting, setSorting] = useState<MRT_SortingState>([]);
    38 const [pagination, setPagination] = useState<MRT_PaginationState>({
    39 pageIndex: 0,
    40 pageSize: 10,
    41 });
    42
    43 //if you want to avoid useEffect, look at the React Query example instead
    44 useEffect(() => {
    45 const fetchData = async () => {
    46 if (!data.length) {
    47 setIsLoading(true);
    48 } else {
    49 setIsRefetching(true);
    50 }
    51
    52 const url = new URL(
    53 '/api/data',
    54 process.env.NODE_ENV === 'production'
    55 ? 'https://www.material-react-table.com'
    56 : 'http://localhost:3000',
    57 );
    58 url.searchParams.set(
    59 'start',
    60 `${pagination.pageIndex * pagination.pageSize}`,
    61 );
    62 url.searchParams.set('size', `${pagination.pageSize}`);
    63 url.searchParams.set('filters', JSON.stringify(columnFilters ?? []));
    64 url.searchParams.set('globalFilter', globalFilter ?? '');
    65 url.searchParams.set('sorting', JSON.stringify(sorting ?? []));
    66
    67 try {
    68 const response = await fetch(url.href);
    69 const json = (await response.json()) as UserApiResponse;
    70 setData(json.data);
    71 setRowCount(json.meta.totalRowCount);
    72 } catch (error) {
    73 setIsError(true);
    74 console.error(error);
    75 return;
    76 }
    77 setIsError(false);
    78 setIsLoading(false);
    79 setIsRefetching(false);
    80 };
    81 fetchData();
    82 // eslint-disable-next-line react-hooks/exhaustive-deps
    83 }, [
    84 columnFilters,
    85 globalFilter,
    86 pagination.pageIndex,
    87 pagination.pageSize,
    88 sorting,
    89 ]);
    90
    91 const columns = useMemo<MRT_ColumnDef<User>[]>(
    92 () => [
    93 {
    94 accessorKey: 'firstName',
    95 header: 'First Name',
    96 },
    97 //column definitions...
    115 ],
    116 [],
    117 );
    118
    119 return (
    120 <MaterialReactTable
    121 columns={columns}
    122 data={data}
    123 enableRowSelection
    124 getRowId={(row) => row.phoneNumber}
    125 initialState={{ showColumnFilters: true }}
    126 manualFiltering
    127 manualPagination
    128 manualSorting
    129 muiToolbarAlertBannerProps={
    130 isError
    131 ? {
    132 color: 'error',
    133 children: 'Error loading data',
    134 }
    135 : undefined
    136 }
    137 onColumnFiltersChange={setColumnFilters}
    138 onGlobalFilterChange={setGlobalFilter}
    139 onPaginationChange={setPagination}
    140 onSortingChange={setSorting}
    141 rowCount={rowCount}
    142 state={{
    143 columnFilters,
    144 globalFilter,
    145 isLoading,
    146 pagination,
    147 showAlertBanner: isError,
    148 showProgressBars: isRefetching,
    149 sorting,
    150 }}
    151 />
    152 );
    153};
    154
    155export default Example;
    156

    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.


    Demo

    1HughMungusMale42
    2LeroyJenkinsMale51
    3CandiceNutellaFemale27
    4MicahJohnsonOther32

    Rows per page

    1-4 of 4

    Source Code

    1import React, { useMemo } from 'react';
    2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';
    3
    4export type Person = {
    5 id: number;
    6 firstName: string;
    7 lastName: string;
    8 gender: string;
    9 age: number;
    10};
    11
    12const Example = () => {
    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 );
    47
    48 const data = useMemo<Person[]>(
    49 //data definitions...
    82 );
    83
    84 return (
    85 <MaterialReactTable
    86 columns={columns}
    87 data={data}
    88 initialState={{ showColumnFilters: true }} //show filters by default
    89 muiTableHeadCellFilterTextFieldProps={{
    90 sx: { m: '0.5rem 0', width: '100%' },
    91 variant: 'outlined',
    92 }}
    93 />
    94 );
    95};
    96
    97export default Example;
    98

    Custom Filter Components

    If you need custom filter components that are much more complex than text-boxes and dropdowns, you can create and pass in your own filter components using the Filter column option.

    View Extra Storybook Examples