Overview
Introduction
Section titled “Introduction”Row grouping buckets the grid’s rows by the value of one or more columns and
draws a collapsible header row for each group. Instead of one long flat list,
readers see the data organised — Region → 8 groups, each openable to reveal its
rows — with an optional aggregate summary (sum, average, count…) in every
header. Nest several columns and the groups nest too.
Grouping ships in @zengrid/enterprise. It’s built on the core full-width row
mechanism: a group header is a single cell spanning every column, so it rides the
grid’s virtualization and scrolls with the body like any other row.
How it works
Section titled “How it works”Create a grouping manager with rowGrouping(), hand its provider to the grid’s
fullWidthProvider option, then attach() the grid and give it the flat rows with
setData():
import { rowGrouping } from '@zengrid/enterprise/grid';
// Group by the Region column (index 2), summing Revenue (3), averaging MRR (4).const grouping = rowGrouping({ groupBy: [2], aggregations: { 3: 'sum', 4: 'avg' },});
const grid = new Zengrid(el, { fullWidthProvider: grouping.provider, columns: [/* … */],});
grouping.attach(grid);grouping.setData(rows); // the flat, ungrouped rowsThe manager owns the displayed rows from here: it buckets rows into a tree,
interleaves a header row before each group, and pushes the result to the grid.
Clicking a header (or its chevron) collapses or expands that group — the manager
recomputes which rows are visible and re-renders.
Options
Section titled “Options”groupBy— the columns to group by, outermost first. Each entry is a source column index (positional data) or a{ col, comparator }spec to control how sibling groups are ordered. Pass several to nest the groups.aggregations— a map of column index → reducer ('sum','avg','min','max','count','first', or your own(values) => value). Each result is shown in the group header.aggLabel(col, value, ctx)— format an aggregate for the header (e.g. as currency). Return''to hide one.groupLabel(ctx)— the header’s title text; defaults to the group value.expandedByDefault— start groups collapsed by setting this tofalse.onExpandedChanged({ path, expanded })— notified on every expand/collapse.
The manager exposes expandAll(), collapseAll(), setExpanded(path, bool),
toggle(path), isExpanded(path) and getGroupCount() — drive them from your own
toolbar or keyboard shortcuts.
Try it live
Section titled “Try it live”Each tab is a different facet of grouping. Edit the snippet — change groupBy, add
an aggregate, or nest a second column — and the grid re-renders.
groupBy: [2] buckets by Region. Click a header to expand/collapse. Change the index (try 1 for Role or 5 for Status) and re-run.
- The manager owns the displayed rows. It transforms your flat rows into
header + leaf rows and calls
setDatafor you. Keep the flat data as your source of truth and feed it in throughgrouping.setData()(re-call it when the data changes). - Grouping keys are positional. With array-backed rows,
groupByandaggregationsindex into the row array (regionis column 2,revenueis 3), the same indices yourcolumnsmap to. - Headers span the content width. A group header is a full-width row, so it scrolls with the body and its aggregate summary sits at the right edge.
- Nesting is unbounded. Add more columns to
groupBy; each header indents by its depth, andexpandAll/collapseAllreach every level.
- Grouping Data — supply and shape the rows you group.
- Group Display Types — group rows vs. a single group column.
- Expanding Groups — control which groups open, and react to expand/collapse.