Shadcn React Table

Search documentation

Search the docs

Filter modes

Filter modes let users change how a column's filter is applied — for example matching with Contains, Starts with, Equals, Between, Greater than, or Empty. With enableColumnFilterModes: true (the default) each filter field shows a mode menu offering the modes appropriate to that column's meta.filterVariant.

Filter modesSwitch a column's match mode (contains, starts with, between, …).
GitHub
ID
2261
45000134754
099
AvaThompsonOwnerEngineeringactive22$45,000Jan 2, 2023
0%
LiamNguyenAdminMarketinginactive25$47,137Jan 13, 2023
9%
NoahSilvaEditorDesignpending28$49,274Jan 24, 2023
18%
EmmaCarterViewerSalesactive31$51,411Feb 4, 2023
27%
OliviaRossiOwnerSupportinactive34$53,548Feb 15, 2023
36%
WilliamWalkerAdminEngineeringpending37$55,685Feb 26, 2023
45%
SophiaPatelEditorMarketingactive40$57,822Mar 9, 2023
54%
JamesMullerViewerDesigninactive43$59,959Mar 20, 2023
63%
IsabellaParkOwnerSalespending46$62,096Mar 31, 2023
72%
LucasReyesAdminSupportactive49$64,233Apr 11, 2023
81%
$4,120,536
Rows per page
1–10 of 48

Setting the initial mode

Set a column's starting mode with meta.filterMode.

tsx
import { DataTable, useDataTable } from "@/components/ui/data-table"

const columns = [
  {
    accessorKey: "title",
    header: "Title",
    meta: { filterVariant: "text", filterMode: "startsWith" },
  },
  {
    accessorKey: "score",
    header: "Score",
    meta: { filterVariant: "range", filterMode: "between" },
  },
]

const table = useDataTable({ data, columns, getRowId: (row) => row.id })
return <DataTable table={table} />

Toggling the mode menu

enableColumnFilterModes is true by default. Turn it off globally to hide every mode menu, or override it per column with meta.enableColumnFilterModes.

tsx
const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableColumnFilterModes: false,
})
tsx
const columns = [
  // mode menu hidden for this column only
  { accessorKey: "id", header: "ID", meta: { enableColumnFilterModes: false } },
]

Restricting the available modes

Limit a column's mode menu to a specific subset (and order) with meta.columnFilterModeOptions. Only modes valid for the column's variant are kept (plus any custom functions); include the column's default mode.

tsx
const columns = [
  {
    accessorKey: "title",
    header: "Title",
    meta: {
      filterVariant: "text",
      filterMode: "contains",
      columnFilterModeOptions: ["contains", "startsWith", "equals"],
    },
  },
]

To restrict every column at once, pass columnFilterModeOptions to useDataTable. Each column keeps the modes its variant supports; a column's own meta.columnFilterModeOptions wins.

tsx
const table = useDataTable({
  data,
  columns,
  columnFilterModeOptions: ["contains", "equals", "between", "betweenInclusive"],
})

Custom filter functions

Add your own filter functions with the filterFns option. Each one takes TanStack's filter function arguments — (row, columnId, filterValue) — and returns whether the row passes. Then use it by name:

  • in a mode menu, by listing it in meta.columnFilterModeOptions or columnFilterModeOptions;
  • as a column's starting mode, with meta.filterMode;
  • as a column's fixed filter (no mode menu), with filterFn;
  • in the global search, by listing it in globalFilterModeOptions — see Global search.
tsx
const table = useDataTable({
  data,
  columns: [
    {
      accessorKey: "name",
      header: "Name",
      meta: {
        columnFilterModeOptions: ["contains", "startsWith", "wordStartsWith"],
      },
    },
  ],
  filterFns: {
    wordStartsWith: (row, columnId, value) =>
      String(row.getValue(columnId))
        .toLowerCase()
        .split(/\s+/)
        .some((word) => word.startsWith(String(value).toLowerCase())),
  },
  localization: { filterModes: { wordStartsWith: "Any word starts with" } },
})

The menu labels a custom function with localization.filterModes[name], or the name itself when there is no label. The names are read when the table is created, so define the functions outside your component (or memoize them).

Custom filter functionA named filter function offered in the column's mode menu.
GitHub
Ava Thompsonava.thompson@example.comBerlin
Liam Nguyenliam.nguyen@example.comTokyo
Noah Silvanoah.silva@example.comAustin
Emma Carteremma.carter@example.comLyon
Olivia Rossiolivia.rossi@example.comMilan
William Walkerwilliam.walker@example.comToronto
Sophia Patelsophia.patel@example.comOslo
James Mullerjames.muller@example.comLisbon
Isabella Parkisabella.park@example.comBerlin
Lucas Reyeslucas.reyes@example.comTokyo
Rows per page
1–10 of 48

Custom mode menu

Replace the built-in radio items with your own using renderColumnFilterModeMenuItems. You get the allowed modes, the currentMode, and an onSelect(mode) to switch.

tsx
import { DropdownMenuItem } from "@/components/ui/dropdown-menu"

const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  renderColumnFilterModeMenuItems: ({ modes, currentMode, onSelect }) =>
    modes.map((mode) => (
      <DropdownMenuItem
        key={mode}
        disabled={mode === currentMode}
        onClick={() => onSelect(mode)}
      >
        {mode}
      </DropdownMenuItem>
    )),
})

The global-search mode menu has the same hook: renderGlobalFilterModeMenuItems — see Global search.

Localizing mode labels

Mode menu labels are localizable via localization.filterModes. Labels you pass are merged with the built-in ones, so you only need to list the modes you change or add.