Skip to content

Faceted List Filter

Use the Faceted List filter for a searchable value checklist that also shows how many rows contain each value and how many remain visible after other filters.

Source code
TypeScriptts
grid.plugins = [AdvanceFilterPlugin];
grid.columns = [
  {
    prop: 'region',
    name: 'Region',
    filter: ['string', FILTER_FACETED_LIST],
  },
];
grid.filter = true;

return [
  { region: 'EMEA' },
  { region: 'APAC' },
  { region: 'EMEA' },
  { region: 'Americas' },
  { region: 'APAC' },
  { region: 'EMEA' },
];
import {
AdvanceFilterPlugin,
FILTER_FACETED_LIST,
} from '@revolist/revogrid-pro';
import '@revolist/revogrid-pro/dist/revogrid-pro.css';
grid.plugins = [AdvanceFilterPlugin];
grid.columns = [
{ prop: 'region', name: 'Region', filter: ['string', FILTER_FACETED_LIST] },
];
grid.filter = true;

The body reads both all-row and visible-row value counts. The two counts make it easier to understand which options remain after other column filters are active.

Saved operatorValue shapeMatches
facetedListInclude(string | number | boolean | null)[]Values in the saved list
facetedListExclude(string | number | boolean | null)[]Values outside the saved list

Typed identity is preserved: 1, '1', and true are different options. null is shown as (Blank) and '' as (Empty). Non-finite numbers, arrays, objects, and undefined are not facet values.

If the column uses ColumnDropdown with object options, the facet editor, condition description, and header selection automatically show each option’s label while saved conditions continue to contain its typed value.

import { ColumnDropdown } from '@revolist/revogrid-pro';
const statuses = [
{ value: 10, label: 'Open' },
{ value: 20, label: 'Closed' },
];
grid.columnTypes = { dropdown: ColumnDropdown };
grid.columns = [{
prop: 'statusId',
columnType: 'dropdown',
filter: ['number', FILTER_FACETED_LIST],
dropdown: { source: statuses },
}];
grid.source = [{ statusId: 10 }, { statusId: 20 }];

For remote or separately loaded labels, configure facetedList.formatLabel globally or under facetedList.columns[prop]. The explicit formatter wins over the dropdown label and affects presentation only.

grid.filter = {
facetedList: {
columns: {
statusId: { formatLabel: value => statusLabels.get(value as number) },
},
},
};
grid.filter = {
multiFilterItems: {
region: [
{
id: 1,
type: 'facetedListInclude',
value: ['EMEA', 'APAC'],
relation: 'and',
},
],
},
};

The editor may serialize the smaller equivalent include or exclude list. Selecting every available value removes the condition; selecting none is represented as a non-empty exclusion list so local and remote behavior remain consistent.

Facets use the valueCounts aggregate in two scopes:

  • all describes the complete source available to the filter.
  • visible applies all active filters except the current facet’s own condition.

Local grids derive both from provider-backed row state. Pagination and infinite-scroll grids should supply complete structured-filter aggregates when browser rows are only a window of the remote result.

  • Do not stringify typed values before restoring them unless the source column is also text; numeric 1 and string '1' are intentionally distinct.
  • Do not put whole option objects in facet conditions. Store their scalar value; use dropdown options or formatLabel for presentation.
  • Do not assume the UI always saves an include condition. It chooses a smaller equivalent include or exclude representation.
  • Do not use this type for arbitrary array-valued cells. Use the Array and Tags filter for arrays.
  • Do not treat the visible count as the total source count; it reflects other active filters.