demo D54
The filter menu: JavaScript Data Grid Demo
Per-column filtering with the operators each type supports, plus an inline filter row that writes the same condition
filterRow · filters.set(tree)
This grid filters each column from a menu that offers only the operators that make sense for that column's type. It is the default way a reader narrows a table without leaving the grid, with the right controls for text, numbers and dates each. Switch on the filter row above the grid and the same condition can be typed straight under the heading instead.
The configuration
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.103.2/lattice-grid.min.css">
<script src="https://cdn.latticegrid.dev/lattice-grid@1.103.2/lattice-grid.min.js"></script>
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 10px">
<span>Filter row</span>
<button id="fr-off" type="button" aria-pressed="true">Off</button>
<button id="fr-on" type="button" aria-pressed="false">On</button>
</div>
<div id="grid" style="height: 500px"></div>
<script>
// Every column carries a filter, so the header menu offers the kind that
// fits its type: text, set, number or date. filterRow starts off; the two
// buttons below flip it live. Whichever one is used, the grid writes the
// same filters model, so the other one always agrees.
const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
rowKey: 'id',
filterRow: false,
toolPanel: { side: 'left', panels: ['filters', 'columns'], actions: ['restore'], exportName: 'lattice-demo' },
columns: [
{ field: 'service', title: 'Service', layout: { pin: 'start', width: 140 }, filter: true },
{ field: 'team', title: 'Team', filter: true },
{ field: 'owner', title: 'Owner', filter: true },
{ field: 'tier', title: 'Tier', cell: { decoration: 'pill', variant: { map: { gold: 'warning', silver: 'neutral', bronze: 'info' } } }, filter: true },
{ field: 'state', title: 'State', cell: { decoration: 'dot', variant: { map: { healthy: 'success', degraded: 'warning', failing: 'danger', unknown: 'neutral' } } }, filter: true },
{ field: 'region', title: 'Region', filter: true },
{ field: 'active', title: 'Active', type: 'boolean', filter: true },
{ field: 'deprecated', title: 'Deprecated', type: 'boolean', filter: true },
{ field: 'version', title: 'Version', layout: { width: 100 }, filter: true },
{ field: 'instances', title: 'Instances', type: 'number', filter: true },
{ field: 'cpuCores', title: 'vCPU', type: 'number', filter: true },
{ field: 'memoryGb', title: 'Memory GB', type: 'number', filter: true },
],
rows, // 20,000 service records
});
function setFilterRow(on) {
grid.set('filterRow', on);
document.getElementById('fr-off').setAttribute('aria-pressed', String(!on));
document.getElementById('fr-on').setAttribute('aria-pressed', String(on));
}
document.getElementById('fr-off').addEventListener('click', () => setFilterRow(false));
document.getElementById('fr-on').addEventListener('click', () => setFilterRow(true));
</script>
Per-column filtering with type-aware operators
A filter menu is the default way a user narrows a table without leaving the grid: click a header’s filter icon, and a panel opens with the operators that make sense for that column’s data. A JavaScript data grid handling mixed content needs this to be type-aware rather than one generic text box, since “contains” is the right default for a name column, “between” for a price column, and “is after” for a date column. Lattice Grid infers the operator set from the column’s declared type, then falls back to a text-contains filter for anything undeclared, so the menu never offers a numeric range on a string field.
The filters.set(tree) call applies a filter programmatically, taking the same tree structure the menu builds when a user picks conditions and combines them with AND or NOR. Passing a tree through this call and opening the menu afterwards shows the equivalent conditions already selected, so the UI and the API stay in sync. Filtering runs against the underlying row model rather than the rendered DOM, so narrowing a column on a dataset with hundreds of thousands of rows does not require re-measuring rows that stay hidden. Each filter menu is keyboard-reachable: Enter on a header’s filter icon opens the panel, and focus moves straight to the first operator control.
How do you filter a column programmatically instead of through the menu UI?
Call filters.set(tree) with a condition tree matching the column you want to filter, using the same field names and operators the filter menu itself produces. The grid applies it immediately and reflects the same state back in the menu if a user opens it, so a saved filter or a URL parameter can drive the table without simulating clicks. See the step-by-step how to add a set filter to a column guide for a runnable example of the checkbox-list variant and the source on GitHub.
An inline filter row beside the menu
Turn the toggle above the grid to On and a row of inline filter cells appears directly under the headings: a text box for a name column, a number box with its operator for a cost column, a date picker for a deploy date, all without opening anything. It is not a second filter system sitting beside the first one. Typing into a cell in the row and opening that same column’s menu afterwards shows the identical condition, because both write the one filter tree the grid already keeps; a condition set from the menu shows up in the row’s box the same way round. A reader who wants to narrow several columns at a glance uses the row; a reader who wants the full operator picker for one column still has the menu open at the same time.