Skip to content

Selection Filter

Selection filters let users include or exclude values through a searchable checkbox list. The list is a virtualized nested revo-grid, so large option sets render only the visible rows while preserving sorting, search, and checkbox behavior.

Use the default interaction for immediate checkbox updates. When users should review a staged checklist and choose Apply, use the dedicated Excel-Style Filter preset.

Source code
TypeScriptts
grid.plugins = [AdvanceFilterPlugin];
grid.columns = [
  { prop: 'fruit', name: 'Fruit', filter: [FIlTER_SELECTION] },
];
grid.filter = true;

return [
  { fruit: 'Apple' },
  { fruit: 'Banana' },
  { fruit: 'Apple' },
  { fruit: 'Pear' },
];

Add AdvanceFilterPlugin, then include selection in the column’s filter families:

import { AdvanceFilterPlugin, FIlTER_SELECTION } from '@revolist/revogrid-pro';
import '@revolist/revogrid-pro/dist/revogrid-pro.css';
grid.plugins = [AdvanceFilterPlugin];
grid.columns = [
{
name: 'Fruit',
prop: 'name',
filter: ['string', FIlTER_SELECTION],
},
];
grid.filter = true;
grid.source = [{ name: 'Apple' }, { name: 'Banana' }, { name: 'Pear' }];

By default, checked values are included and unchecked values are stored as an excluded-value Set. Opening and closing a fully selected list does not create a filter.

Add grid.filter = { selection: { sortDirection: 'asc' } } when the options should be sorted rather than kept in source order.

selection.excelMode: 'windows' changes selection-filter columns into a staged, spreadsheet-style checklist. It keeps the same excluded-value Set model but adds Apply, Cancel, tri-state Select All, blanks, search actions, and optional date hierarchies.

See Excel-Style Filter for the interactive four-framework example and complete behavior reference. This heading remains available for links created before the guide was separated.

The selection popup keeps the search row fixed at the top and renders option rows through an internal revo-grid.

  • Search still matches normalized option value.
  • Select-all only affects currently searched and visible option rows.
  • Checked state still means the value is included; unchecked values are stored in the selection filter’s excluded-value Set.
  • Opening and closing a fully selected popup does not create an empty selection filter, so FilterHeaderPlugin keeps showing All.
  • Group rows are visual only; option checkboxes still belong to leaf option rows.

The old .filter-list li DOM shape is not part of the public API. Use the visible option behavior or .filter-list-option when tests need to interact with option rows.

When a column defines cellParser, the built-in selection option loader uses the parsed value for option labels, quick search, and row comparison. This lets rows keep identifiers or structured values while the filter presents and compares the normalized value returned by the parser. Context-aware cascading options use the same parsed values.

const statusLabels = {
1: 'Active',
2: 'Paused',
};
grid.columns = [
{
prop: 'status',
name: 'Status',
filter: ['selection'],
cellParser: (model, column) => statusLabels[model[column.prop]],
},
];

If you provide selection.getItems, that custom loader remains the explicit source for option values and labels. See the Core guide on filtering parsed values for the underlying cellParser contract.

The built-in selection and slider option loaders emit the cancelable beforefilteroptionsourcerow event before a source row contributes a value. Cancel the event to exclude application- or plugin-owned synthetic rows without coupling Advanced Filter to their data shape.

import { BEFORE_FILTER_OPTION_SOURCE_ROW_EVENT } from '@revolist/revogrid-pro';
grid.addEventListener(BEFORE_FILTER_OPTION_SOURCE_ROW_EVENT, (event) => {
if (event.detail.row.__summaryRow) {
event.preventDefault();
}
});

Grouping rows are excluded before the event is emitted. The @revolist/pivot plugin uses this extension automatically for subtotal and grand-total rows. A custom selection.getItems loader remains fully application-owned and does not scan or emit events for grid source rows.

By default, the selection popup search input does two things:

  • narrows the option rows shown inside the popup
  • applies a hidden quickSearch filter to the grid rows

This preserves the existing behavior for users who expect the grid to narrow while they type. Set selection.quickSearchFiltering to false when search should only help users find values in the popup and should not change the grid rows until they check or uncheck selection values.

grid.filter = {
selection: {
quickSearchFiltering: false,
},
};

When selection values are IDs but the popup renders names, use selection.quickSearchFilter to match the text users see. The matcher receives normalized search, normalized option value, display label, original item, and columnProp. If quickSearchFiltering remains enabled, grid rows are filtered by the matched option values, so row data can still store IDs.

grid.filter = {
selection: {
getItems: {
ownerId: () => [
{ value: 'usr-1', label: 'Ana Silva', email: '[email protected]' },
{ value: 'usr-2', label: 'Maks Doe', email: '[email protected]' },
],
},
quickSearchFilter: {
ownerId: ({ search, label, item }) =>
`${label} ${item.email}`.toLowerCase().includes(search),
},
},
};

Enable context-aware selection options with selection.cascadeOptions.enabled.

  • For column X, options are built from rows matching all active filters except filters for X.
  • This keeps current-column values reversible while still narrowing related column options.
  • optionVisibility supports hide, disable, and show; hide is the default.
  • Header totals and tooltips always describe context-valid values, even when the popup shows the complete domain.
  • The feature is opt-in, and default behavior is unchanged when omitted.
grid.filter = {
selection: {
cascadeOptions: {
enabled: true,
optionVisibility: 'hide',
},
},
};

See Cascading Selection Filters for a detailed comparison of all three modes and preserved exclusion behavior.

By default, the selection filter builds its checkbox list from the current grid data. Use filter.selection.getItems when the list should come from somewhere else, for example:

  • server-side or infinite-scroll datasets
  • a curated allow-list of accepted values
  • normalized values that differ from the rendered cell text

Default lists are rebuilt when the popup opens. If a cell value is edited, rows are removed, or grid.source is replaced, the next selection popup reflects the latest column values. Values that no longer exist in the source are not shown unless you provide them through a custom selection.getItems loader.

When pinned rows should not contribute checkbox values, keep the default loader and restrict its row stores:

grid.filter = {
selection: {
sourceRowTypes: ['rgRow'],
},
};

The loader receives the current column prop and may return data synchronously or asynchronously.

grid.filter = {
selection: {
getItems: async (prop) => {
if (prop !== 'name') {
return [];
}
const response = await fetch('/api/filter-options/names');
const items = await response.json();
return items.map((item: { id: string; title: string }) => ({
value: item.id.toLowerCase(),
label: item.title,
}));
},
},
};

If only some columns need custom values, pass a record keyed by column prop:

grid.filter = {
selection: {
getItems: {
name: async () => [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
],
category: () => [
{ value: 'fresh', label: 'Fresh' },
{ value: 'frozen', label: 'Frozen' },
],
},
},
};

Keep value aligned with the value used during filter comparison. The built-in selection filter compares lower-cased string values, so custom lists should usually provide lower-cased value fields.

Use selection.itemTemplate to render badges, icons, or richer labels inside the selection popup. The checkbox remains controlled by the filter plugin; the template only replaces the content next to it.

To reuse an existing column renderer without defining a second template, enable selection.syncCellTemplate. The option item is exposed as a synthetic row model, including metadata returned by selection.getItems, and the current column prop is set to the normalized filter value.

grid.filter = {
selection: {
syncCellTemplate: {
availability: true,
},
getItems: {
availability: () => [
{ value: 'in stock', label: 'In stock', tone: 'green' },
{ value: 'backorder', label: 'Backorder', tone: 'amber' },
],
},
},
};
grid.filter = {
selection: {
getItems: {
availability: () => [
{ value: 'in stock', label: 'In stock', tone: 'green' },
{ value: 'backorder', label: 'Backorder', tone: 'amber' },
{ value: 'seasonal', label: 'Seasonal', tone: 'indigo' },
],
},
itemTemplate: {
availability: (h, { item, label, checked }) =>
h(
'span',
{
class: `availability-badge availability-badge--${item.tone}`,
'data-selected': String(checked),
},
label,
),
},
},
};

itemTemplate receives:

  • columnProp: Current column property.
  • item: Original item returned by selection.getItems or the default source loader.
  • value: Normalized value used by selection filtering.
  • label: Display label.
  • checked: Whether the option is currently included in the result.

Use selection.optionProgress for a responsive distribution bar inside the selection-owned option row. The label, track, and formatted value share the available width, and unchecked options switch to the muted visual state automatically. Values read item metadata returned by selection.getItems.

grid.filter = {
selection: {
getItems: {
status: () => [
{ value: 'processing', label: 'Processing', count: 42 },
{ value: 'shipped', label: 'Shipped', count: 28 },
],
},
optionProgress: {
status: {
valueProp: 'count',
getMax: ({ values }) => Math.max(1, ...values),
formatValue: value => `${value} rows`,
},
},
},
};

Use getValue instead of valueProp for derived values, and max or getMax to control the range. showValue: false hides the trailing value while keeping the accessible progressbar. ariaLabel accepts a string or formatter.

For secondary metadata that is not progress, selection.optionColumns still appends ordinary read-only RevoGrid columns after the selection-owned checkbox and label column.

Selection option rows can be grouped by fields on the option item. This is useful for large curated lists where users need a hierarchy such as family and color, region and country, or category and status.

grid.filter = {
selection: {
grouping: {
name: {
props: ['family', 'color'],
expandedAll: true,
},
},
getItems: {
name: () => [
{ value: 'apple', label: 'Apple', family: 'Tree fruit', color: 'Red' },
{ value: 'pear', label: 'Pear', family: 'Tree fruit', color: 'Green' },
{ value: 'lemon', label: 'Lemon', family: 'Citrus', color: 'Yellow' },
],
},
},
};

selection.grouping can also be a single GroupingOptions object when every selection-filter column should use the same grouping configuration.

The selection list is a nested grid, and you can pass plugins or grid settings to that nested grid when you need additional rendering behavior.

import { AdvanceFilterPlugin } from '@revolist/revogrid-pro';
class SelectionListPlugin {
constructor(selectionGrid) {
selectionGrid.setAttribute('data-selection-list-plugin', 'mounted');
}
}
grid.plugins = [AdvanceFilterPlugin];
grid.filter = {
selection: {
plugins: {
name: [SelectionListPlugin],
},
gridSettings: {
name: {
theme: 'compact',
rowSize: 32,
frameSize: 2,
hideAttribution: true,
},
},
},
};

selection.plugins and selection.gridSettings accept either a global value or a record keyed by column prop.

The filter list owns source, columns, and grouping so filtering, checkbox state, and virtualization stay consistent. Use selection.grouping for grouped option rows instead of gridSettings.grouping.

Selection filters store unchecked values as an excluded-value Set. To predefine a selection filter, add a hidden selection filter with values that should be excluded.

grid.filter = {
multiFilterItems: {
name: [
{
id: 0,
type: 'selection',
value: new Set(['banana', 'lemon']),
relation: 'and',
hidden: true,
},
],
},
};

The Excel-style demo uses this pattern for the Fruit column, so two fruit values are already unchecked when it loads. See Filter State and Presets before persisting this model because a Set is not directly JSON-safe.

OptionPurpose
sortDirectionSort options with 'asc', 'desc', or 'none'.
excelModeSet to 'windows' for the dedicated Excel-style checklist.
quickSearchFilteringChoose whether popup search also filters grid rows; defaults to true.
quickSearchFilterMatch search text against labels or custom item metadata.
sourceRowTypesChoose which row stores feed the default option loader.
getItemsProvide synchronous or asynchronous custom options globally or by column.
itemTemplate / syncCellTemplateCustomize option content while the plugin retains checkbox behavior.
optionProgressAdd selection-owned responsive progress with checked and unchecked visual states.
optionColumnsAppend read-only metadata columns for non-progress option details.
groupingGroup option rows using fields returned by getItems.
plugins / gridSettingsConfigure the nested option grid without replacing its owned source, columns, or grouping.
cascadeOptionsBuild options from rows matching filters in other columns.

Default-mode localization includes selectionTitle and selectionSearchPlaceholder. Excel mode adds the action and blank captions documented in Excel-Style Filter.