Selection Rules
The selectAll API selects cells by predicate - matching on facet dimension, facet value, or cell data - and applies attributes to them. Attributes include CSS styles, renderer overrides, column sizing, and data grouping tags.
The selection rules API lets you apply styles or override renderers for cells that match a predicate. Rules target facet cells (headers) by dimension name and value, or data cells by their value. Multiple rules can stack - all matching rules are applied in order.
This is separate from the cell/row/column selection API (selectCellByDataIndex, etc.) which highlights individual cells. The selectAll API is for bulk conditional formatting.
Creating rules
Start with grid.selectAll(predicate) to create a Selection builder. The predicate matches facet cells.
const selection = grid.selectAll((dim, dimVal, path) => {
return dim === "Region" && dimVal === "USA";
});The predicate receives three arguments:
dim- the dimension name (fromFacetDef.facetFieldorFacetDef.text)dimVal- the facet cell's value, ornullfor merged/spanned cellspath- ancestor facet values as[dimName, dimValue][]pairs, from the outermost level down to (but not including) the current level
The predicate is called for each facet level. It returns true if the cell matches.
Chaining predicates
Chain .selectAll() to add more facet predicates. All predicates are AND-ed - a cell must match all of them.
grid
.selectAll((dim, dimVal) => dim === "Quarter" && dimVal === "Q1")
.selectAll((dim, dimVal) => dim === "Measure" && dimVal === "Revenue")
.style((el) => { el.style.fontWeight = "bold"; });This targets cells where Quarter is Q1 and Measure is Revenue.
Applying styles
Use .style(fn) to apply CSS to matching cells. The function receives the cell's DOM element.
grid
.selectAll((dim, dimVal) => dim === "Region" && dimVal === "USA")
.style((el) => {
el.style.backgroundColor = "#e3f2fd";
el.style.fontWeight = "600";
});Overriding renderers
Use .prop(props) to override the renderer or column sizing for matching cells.
import { SelectionProps } from "grid";
grid
.selectAll((dim, dimVal) => dim === "Measure" && dimVal === "Trend")
.prop({
trackRenderer: myCustomFacetRenderer,
colSize: { strategy: "clamped-width", maxWidthInPx: 120 },
});SelectionProps fields:
interface SelectionProps {
cellRenderer?: CellRenderer<any>; // override data cell renderer
trackRenderer?: FacetCellRenderer; // override facet cell renderer
colSize?: ColAutoSizeConfig; // override column sizing
}Data cell predicates
Use .selectAllCell(predicate) to target data cells by value. Cell predicates only apply to data cells (not facet cells). Combine with facet predicates to narrow the scope.
grid
.selectAll((dim, dimVal) => dim === "Measure" && dimVal === "Revenue")
.selectAllCell((value) => value > 10000)
.style((el) => { el.style.color = "green"; });This highlights data cells where Revenue exceeds 10,000.
Grouping
Use .group(value, name?) to tag matching cells with a data attribute. This is a convenience wrapper around .style() that sets data-sel-grp-{name}="{value}" on matching cells.
grid
.selectAll((dim) => dim === "Region")
.group("highlight", "region");
// Sets data-sel-grp-region="highlight" on matching cellsRemoving rules
Every .style(), .prop(), and .group() call returns the selection builder. Call .undo() to remove all rules added through that builder.
const sel = grid
.selectAll((dim, dimVal) => dim === "Region" && dimVal === "USA")
.style((el) => { el.style.backgroundColor = "#e3f2fd"; });
// Later: remove the styling
sel.undo();Removing rules triggers a re-render automatically.
How rules are evaluated
During each render cycle, the layout evaluates rules for every rendered cell:
- Facet cells: the layout calls
evaluateRulesForFacetCellwith the cell's facet path (the values at each facet level) and the facet definitions. Rules that contain cell predicates are skipped. Matching rules can override thetrackRenderer. - Data cells: the layout calls
evaluateRulesForDataCellwith the cell's row facet path, column facet path, facet definitions, and cell value. Both facet and cell predicates must match. Matching rules can override thecellRenderer.
Rules are evaluated in insertion order. When multiple rules match and set a renderer override, the last one wins. Style functions from all matching rules are applied in order.
SelectionRule internals
Internally, each rule is stored as a SelectionRule:
interface SelectionRule {
id: number;
predicates: PredicateNode[];
terminal: TerminalOp;
}
type PredicateNode =
| { type: "facet"; predicate: FacetPredicate }
| { type: "cell"; predicate: CellPredicate };
type TerminalOp =
| { type: "prop"; props: SelectionProps }
| { type: "style"; fn: (container: HTMLElement) => void };A rule's predicates are AND-ed. The terminal is either a property override or a style function. Each .style() or .prop() call on a Selection adds one rule to the store.
Events
All events emitted by the Grid instance - render lifecycle, pagination, viewport changes, selections, and performance metrics.
Themes
How the grid theming system works. Themes are plain objects that map to CSS custom properties on the grid container. Two built-in themes (light and dark) are provided; register custom themes for full control.