Skip to content

Filter Templates

Enterprise

Filter templates let a user snapshot a whole filter — every column’s conditions plus the quick filter — under a name, then re-apply it later in a single click. Each saved template shows an applied / not-applied indicator so it’s obvious which one (if any) matches the grid’s current filter.

import { filterTemplates } from '@zengrid/enterprise/grid';
const templates = filterTemplates(grid, {
storage: 'local', // persist to localStorage (default)
storageKey: 'orders-grid', // give each grid a distinct key
ui: { mount: toolbarEl }, // optional built-in bar
});
templates.save('High value, unshipped'); // snapshot the current filter
templates.apply(id); // restore it later
templates.getActiveId(); // which template matches right now?

filterTemplates() is license-gated (it asserts the filter-templates feature). It builds entirely on core’s grid.filter snapshot/restore API — no special grid setup is needed beyond having filterable columns.

  • 'local' (default) — persists to localStorage, keyed by storageKey. Give each grid on a page its own key.
  • 'memory' — session-only; nothing is written to disk.
  • { load, save } — supply your own backend. load() returns the saved templates, save(templates) persists them — point it at your API to sync per-user.

getActiveId() normalizes the current filter and compares it, order-independently, against each saved template — returning the matching template’s id, or null. The built-in FilterTemplateBar uses it to mark the active chip; subscribe to the manager (and, if you render your own UI, to the grid’s filter:change) to keep it live as the user edits filters.

The FilterTemplateBar renders a chip per template with an applied indicator. Click a chip to apply; use "Save current filter" to snapshot the current filter.

interface FilterTemplate {
id: string;
name: string;
model: FilterSnapshot; // { state: FilterModel[]; quick: { query; columns } }
}
interface FilterTemplatesInit {
storage?: 'local' | 'memory' | { load(): FilterTemplate[]; save(t: FilterTemplate[]): void };
storageKey?: string; // localStorage key for storage: 'local'
templates?: FilterTemplate[]; // seed when storage is empty
ui?: FilterTemplateBarOptions; // mount the built-in bar
}
function filterTemplates(grid, options?): FilterTemplateManager;
interface FilterTemplateManager {
save(name: string): FilterTemplate;
apply(id: string): void;
remove(id: string): void;
rename(id: string, name: string): void;
list(): FilterTemplate[];
getActiveId(): string | null; // the applied indicator
isActive(id: string): boolean;
snapshot(): FilterSnapshot;
setTemplates(templates: FilterTemplate[]): void;
subscribe(cb: () => void): () => void;
destroy(): void; // also tears down an attached bar
}
  • No core change needed. Templates snapshot grid.filter.getState() + getQuick() and restore via setState() / setQuick() — the public Filter API.
  • Distinct storageKey per grid. With storage: 'local', two grids sharing a key would share templates — key them apart.
  • The bar is optional. filterTemplates() returns a headless manager; the FilterTemplateBar (via ui) is one presentation. Build your own from the manager API if you prefer.
  • Active detection is order-independent. Column order and condition order don’t affect whether a template matches — only the effective filter does.