Intelligent GridDocumentation

Sorting & filtering

Sorting

The order follows Excel: numbers < text < booleans < errors. Text uses locale collation (case and accent insensitive, numeric aware, so item 2 sorts before item 10). Blanks always go last, in both directions.

grid.setSort([{ field: 'city', dir: 'asc' }, { field: 'total', dir: 'desc' }]);
grid.toggleSort('qty', /* additive */ true);
grid.getSort();   // [{ field: 'city', dir: 'asc' }, ...]
grid.setSort([]); // clear

Calculated columns sort like any other column: their values are stored in SorlaDB.

The filter menu

The ▾ button opens an Excel AutoFilter popover:

  1. sort buttons
  2. two conditions joined by And / Or (operators depend on the column type). Typing a value without choosing an operator uses contains for text and equals for numbers and dates
  3. a value checklist with search, counts, "(Select all)" and "(Blanks)". Like Excel, it lists the values left by the other columns' filters

Active filters show as chips in the navbar, and the ▾ turns into ⧩.

Filter model

interface Filter {
    values?: unknown[];                                   // checklist, '' = blanks
    conditions?: { op: FilterOperator; value?: unknown; value2?: unknown }[];
    join?: 'and' | 'or';                                  // default 'and'
    formula?: string;                                     // must evaluate to TRUE
    test?: (value: unknown, row: RowData) => boolean;     // your own predicate
}
type FilterModel = Record<string /* field */, Filter>;

All the parts of one filter must match, and all filtered columns must match.

grid.setFilter('status', { values: ['open', ''] });                                    // open or blank
grid.setFilter('total', { conditions: [{ op: 'between', value: 100, value2: 500 }] });
grid.setFilter('name', { join: 'or', conditions: [{ op: 'startsWith', value: 'a' }, { op: 'endsWith', value: 'z' }] });
grid.setFilter('due', { conditions: [{ op: 'lt', value: '2026-12-01' }] });             // ISO or locale text (01/12/2026 in pt-BR)
grid.setFilter('total', { formula: '=[@total] > AVERAGE([total])' });                  // formulas see every row
grid.setFilter('city', { test: value => String(value).length > 8 });

grid.setFilter('status', null);   // remove one
grid.setFilters({ ... });         // replace all
grid.clearFilters();              // filters and search
grid.getFilters();
Operators Applies to
contains notContains equals notEquals startsWith endsWith text, select (case-insensitive; select matches the label or the value)
eq ne gt gte lt lte between number, integer, currency, percent, date, datetime
eq boolean (value: true/false)
empty notEmpty every type

Rules worth knowing:

The navbar search box (or grid.setSearch(text)) keeps rows where any visible column's displayed text contains the search, ignoring case. It is debounced by 200 ms.

How it runs on SorlaDB

Filters compile to a SorlaDB query wherever the Sorla query language can express them: checklists become $in, ranges $gt/$gte/$lt/$lte plus $ne: '' to skip blanks, blanks $eq: '', booleans and select values $eq, and conditions joined by Or become $or. Several filtered columns are combined with $and. Text operators become case-insensitive $regex conditions, and on select columns they match the labels and send the matching values as $in / $nin. Only formulas, test functions and the global search (it matches the displayed text) run as JavaScript predicates.

For nested AND / OR / NOT logic across columns, use the advanced filter. See architecture and SorlaDB status.

In append mode with serverSide: true, sort, filters and search go to your loader instead.

Edit this page on GitHub