Grouping
The grouping transforms underneath groupBy, groupExpansion and the group-by bar.
Last updated November 3, 2026
groupRows reshapes filtered, sorted rows into nested groups, and the other functions here change the two pieces of state it reads: the group-by stack and which groups are collapsed. The view pipeline and the controller call them for you; reach for them directly in a custom adapter or group-by bar.
A GroupByState is readonly GroupByEntry[], outer level first, each entry { columnId, direction? } — a level's own direction orders its group values, not the rows inside a group. A GroupExpansionState is readonly string[]: the ids of the groups collapsed, so a group absent from it is expanded.
Grouping rows#
| Function | Type | Description |
|---|---|---|
groupRows( | readonly DisplayRow< | rows regrouped into groupBy's levels: a header per distinct value at each level, ordered with compareValues, then its nested groups or data rows, depth first. A collapsed group contributes its header only. Returns rows itself when groupBy is empty or names only absent columns. |
groupRowId( | string | A group's id, from the values of its levels outer to inner. Build ids with this, never by hand. |
Filter and sort run first — resolveShownRows does both — and grouping keeps their order within each group. rowIndex is renumbered across the output, headers included.
A DisplayRow<Row> is a data row (ResolvedRow<Row>, with no kind), a group header (ResolvedGroupRow, kind: "group"), or a group's summary row (ResolvedGroupSummaryRow, kind: "group-summary", only from withGroupAggregates). Tell them apart with "kind" in entry, then entry.kind. A ResolvedGroupRow carries:
| Field | Type | Description |
|---|---|---|
groupId | string | Its id — groupRowId( — the entry GroupExpansionState holds when collapsed. |
level | number | Nesting depth, 0 for a top-level group. |
columnId | string | The column this level groups by. |
value | unknown | This level's value — the last entry of path. |
path | readonly unknown[] | The value at every level from the top down to this one. |
expanded | boolean | Whether the group is open. |
count | number | Its leaf rows, collapsed or not. |
rowIndex | number | Its position among the rows as rendered. |
datasetIndex | number | Its position in the whole grouped result, on any page. |
aggregates | AggregateResults | Its own aggregate results, once withGroupAggregates has run; empty otherwise. |
The group-by stack#
| Function | Type | Description |
|---|---|---|
moveGroupByBefore( | GroupByState | columnId placed in front of beforeColumnId, or at the end for null — inserted when it is not grouped yet, moved when it is, so a header dropped on the bar and a chip dragged within it both use it. Returns groupBy itself for a move that changes nothing. |
movesGroupBy( | boolean | Whether that move would change anything, for a drop indicator that promises only real moves. |
A moved level keeps its entry, and so its direction. To add or remove one level, the controller's toggleGroupBy(columnId) appends a column or takes it out.
Expanding and collapsing#
| Function | Type | Description |
|---|---|---|
toggleGroupExpansion( | GroupExpansionState | groupId collapsed if it was open, opened if it was collapsed. |
expandAllGroups( | GroupExpansionState | Empty — every group open. Returns expansion itself when already empty. |
collapseAllGroups( | GroupExpansionState | The id of every group header in rows, an already-grouped display. A group hidden under a collapsed one is not in rows, so it keeps its own state for when its parent reopens. |
The group-by bar#
groupByBarVisibility takes a GroupByBarVisibility — "auto" (the default) shows the bar while anything is grouped or a header that can be dropped on it is being dragged, "always" shows it regardless, and "never" hides it.
In the React grid#
groupableColumns, groupByDraggableColumns and defaultGroupBy turn grouping on — see row grouping.