Skip to main content

Row grouping and aggregation

Group by one or more value columns, choose how group labels are displayed, and calculate aggregates over each group's leaf descendants.

Loading interactive example…
React
<Grid
rowData={rows}
columnDefs={columns}
groupDefaultExpanded={1}
groupRowsSticky
toolbar={{ grouping: true }}
onGridReady={(api) => {
api.dispatch({ type: "rowGroupSet", colIds: ["region", "country"] });
}}
/>

Multi-level row grouping

const options = {
groupDisplayType: "singleColumn",
groupDefaultExpanded: 1,
groupSortMode: "local",
columnDefs: [
{ colId: "region", key: "region", label: "Region", groupable: true },
{ colId: "country", key: "country", label: "Country", groupable: true },
{ key: "revenue", label: "Revenue", type: ColumnType.CURRENCY },
],
} satisfies GridOptions;

api.dispatch({ type: "rowGroupSet", colIds: ["region", "country"] });
api.setAllGroupsExpanded(true);

Use groupRowsSelectable: true when generated group rows should participate in selection, navigation, and copying.

Display and expansion

groupDisplayType accepts singleColumn, multipleColumns, or groupRows. groupDefaultExpanded sets the initial depth; later user expansion remains stable across refreshes (when group values are unchanged). groupRowsSticky docks the active ancestor chain while the body scrolls — see pinned & sticky rows.

The toolbar provides a grouping picker, ordered chips, drag insertion, keyboard reordering, and clear-all behavior. The API can replace grouped columns and expand or collapse all groups in one update, or toggle a single group:

api.dispatch({
type: "groupToggleExpand",
groupId: "the-stable-group-node-id",
expanded: true,
});

Aggregates

Available functions are count, distinct count, sum, average, min, max, and median. The footer scope can be none, current page, or all rows. Grouped client-side rows also receive per-group aggregate values.

const revenue = api.getColumnModel().getByColId("revenue")!;
const orders = api.getColumnModel().getByColId("orders")!;

api.dispatch({
type: "aggregateModelSet",
aggregateModels: [
{ key: revenue.instanceID, type: AggregateType.SUM },
{ key: orders.instanceID, type: AggregateType.COUNT },
],
});

Server-side grouping and aggregation

Server-side grouping requests one parent listing at a time and sends aggregate definitions with the request:

const dataSource: IServerSideDataSource = {
async getRows({ request }) {
// request.groupBy: ["region", "country"]
// request.groupKeys: [{ key: "region", value: "EMEA" }, ...]
return queryOneGroupingLevel(request);
},
getAggregates: async ({ request }) => ({
values: await loadAggregateValues(request),
}),
};

const options = {
rowModelType: "serverSide",
serverSideDataSource: dataSource,
getGroupChildCount: (row) => row.childCount,
} satisfies GridOptions;

Each expanded group loads its own child listing lazily — see server-side data.

Row grouping is also one of pivot mode's three roles: pivoting reuses the group tree and crosses it with pivot columns and aggregates (client-side row model).