Skip to content

Basics

Loading example…

A facet is the answer to "what can I filter this column by, and how many rows would each choice leave?" When a column has no filterOptions, the table works them out: the distinct values for a select or multi-select, and the minimum and maximum for a range or slider.

Counts are shown next to each option, as in Berlin (142), and they respect the other active filters, so the numbers describe what you would actually get.

Client and server

In client mode the facets come from column.getFacetedUniqueValues() and column.getFacetedMinMaxValues() over the currently loaded rows, which is exact because the browser has all of them.

In server mode the browser has one page, so counting locally would be wrong. The table asks the data source instead:

const dataSource: DataSource<Person> = {
  ...createRestDataSource<Person, PeoplePage>({ url: '/api/people', mapQuery, mapResult }),
  fetchFacets: (columnId, query, { signal }) => api.facets(columnId, query, signal),
};

fetchFacets is a method of the data source rather than an option of createRestDataSource, so it is added beside the REST source's own fetch. It is asked for one column at a time.

Facets are requested lazily, the first time a filter control opens, and cached per query, so opening the same dropdown twice costs one round trip. manualFaceting and facetingMode force the choice when the default inference is not what you want, and facets supplies them outright.

Turning it off

enableFacetedValues: false stops the computation for tables where the option lists are static and known. Then filterOptions on the column is the only source, and no counts are shown. showFacetCounts: false keeps the options but drops the numbers.

Customization

filterOptions accepts a static array, a function, or an async function; the control shows a loading state while it resolves. Options carry their own presentation, which is what makes a status filter look like the status column:

col.accessor('status', {
  filterVariant: 'select',
  filterOptions: [
    { value: 'active', label: 'Active', color: '#e6f4ea' },
    { value: 'archived', label: 'Archived', color: '#f1f3f4' },
  ],
});

Those colours are reused by the filter chips.

Limitations

  • Client facets only see loaded rows. With server pagination the browser holds one page, so faceting must come from the server or the counts will describe the page rather than the data set.
  • Counts reflect the other filters, not this one. A multi-select shows what each option would add, which is the standard behaviour but is not the same as the count after applying it.
  • There is no facet for a display column. A facet needs a value; compute it with an accessorFn if you need to filter on something derived.

API

  • DataTableProps: enableFacetedValues, facetingMode, manualFaceting, facets, showFacetCounts.
  • ColumnDef: filterOptions, filterVariant.
  • TableInstance: getColumn(id).getFacetedUniqueValues, getFacetedMinMaxValues, getServerFacets, loadFacets.
  • Utilities: createRestDataSource.