-
Notifications
You must be signed in to change notification settings - Fork 0
Aggregation and Pivot
📝 Generated from
docs/features/aggregation-pivot.md. Edit it there; changes made in the wiki are overwritten.
Transform raw data into meaningful insights with advanced grouping and summary features.
Aggregation allows you to calculate summary values (Sum, Avg, etc.) for groups or the entire dataset.
<DataGrid
rows={rows}
columns={columns}
aggregationModel={{
salary: 'sum',
age: 'avg',
department: 'count'
}}
/>The footer (and apiRef.current.getAggregationResult(), and the aggregationResult passed to slots.footer) always aggregates every data row that passes the current filter. That holds with or without row grouping or tree data, and however many groups are expanded. Group rows show their own subtotals inline; the grand total is computed from the underlying rows, never from those subtotals. (Before v3.0 the footer aggregated the visible rows under grouping, so expanding a group double-counted it, and count / avg were wrong even when collapsed.)
Cells are read the way the grid shows them: a column with a valueGetter (for example total = price × qty) totals the computed values, not row[field].
The footer is laid out exactly like the rows: a hidden column has no footer cell, pinned columns keep their totals under the pinned column (left-pinned first, right-pinned last), and the totals stay aligned while scrolling horizontally, including when column virtualization renders only part of the columns and when the checkbox, detail-panel or row-reorder column is (or is not) pinned.
When a dataSource drives the rows (server or infinite pagination, server sorting, or server filtering), the grid only holds the rows the server returned, so it never totals them itself. The footer shows the aggregationResults returned by getRows, or the result of dataSource.getAggregations.
- A result is only shown for the request it answered: after changing the aggregation model, filter or sort, the footer shows
—until the new totals arrive, and keeps showing—if that request fails (the error is logged). It never shows the previous model's or filter's totals under the new label. - While a
getAggregationsrequest is pending the footer hasaria-busy="true"and the classogx__aggregation-footer--loading. - An inline
aggregationModel={{ salary: 'sum' }}is a new object on every render of your component. The grid compares the model by content, so re-rendering with an equal model neither refetches nor clears the totals.
If the server provides neither aggregationResults nor getAggregations, the footer shows —.
getAggregationPosition(groupNode) controls where aggregation results appear. It is called for every group node (with its current isExpanded) and once with null for the grand total:
-
inline(default for groups): values on the group row. -
footer: values on a subtotal row after the group's children while the group is expanded; the group row shows none. While the group is collapsed there is no subtotal row, so the values stay on the group row. For the grand total (null),'footer'(the default) shows the footer row. -
null: no aggregation for that group (on screen and ingetGroupedExportRows()); for the grand total, the footer row is hidden.
<DataGrid
rows={rows}
columns={columns}
aggregationModel={model}
rowGroupingModel={['department']}
// Subtotal rows below expanded groups, inline values on collapsed ones, and the grand total.
getAggregationPosition={() => 'footer'}
/>Group subtotals and the (n) count next to a group label cover only the rows that pass the filter, like the grand total; a group with no matching row is not shown.
Pivot mode rotates your data, turning row values into dynamically generated columns.
const pivotModel: GridPivotModel = {
rowFields: ['office'], // Dimensions on the Left
columnFields: ['year'], // Dimensions on the Top
valueFields: [ // Values to compute
{ field: 'revenue', aggFn: 'sum', headerName: 'Total Revenue' }
]
};
<DataGrid
rows={rows}
columns={columns}
pivotMode={true}
pivotModel={pivotModel}
/>aggFn is a GridPivotAggFn: 'sum' | 'avg' | 'count' | 'min' | 'max'. unique is available to aggregationModel, but not to pivot value fields.
- Row Fields: These become the static vertical axis of your pivot table.
- Column Fields: Unique values in these fields become new columns.
- Value Fields: The data that gets summarized at the intersection of row and column fields.
The generated value columns are named <field>␟<aggFn> (for example 'salary\u001fsum') without column fields, and <column key>␟<field>␟<aggFn> with them.
-
Filtering. Filters on source fields (including the row fields) and the quick filter are applied to the source rows before pivoting, so every pivot value and the Grand Total reflect them. In pivot mode the quick filter searches every filterable source column. A condition on a generated value column (for example
'salary\u001fsum' > 1000) is applied to the pivot rows. If a filter model mixes both kinds withlogicOperator: 'or', each kind is applied in its own stage, so the result is as if they were joined withand. - Sorting orders the pivot data rows. The Grand Total row always stays last.
-
Pivot row ids are derived from the row-field values (
'__pivot_row__:["Eng"]','__pivot_row__:["North","Q1"]'for two row fields), so they never collide with source row ids and stay the same for the same group when the data changes (v3.0+; they were0, 1, …). -
Grand Total is the last row (id
'__pivot_grand_total__'). It totals the pivot rows shown, recomputed from the raw values (an average is the average of all underlying values, not of the row averages). It is not selected by the header select-all checkbox. When no source row is left, there is no Grand Total row and the no-rows overlay is shown; the value columns stay. -
Row ids. Pivot rows carry their own ids (the
'__pivot_row__:…'ids above and the Grand Total id). YourgetRowIdis not applied to them. -
Groups are formed by each value's displayed string, as in row grouping, so
1and'1'are one group.null,undefinedand''form one blank group, labellednull.
-
Row-label columns keep the source column's
valueFormatter,renderCell,type, alignment andvalueOptions(the formatter and renderer receive a source row of that group). They always show, even ifcolumnVisibilityModelhides the source column of the same field, and arehideable: false. - Value columns are formatted like every other aggregate (see Formatting Totals).
-
Column keys are ordered by value: numbers and dates numerically, strings naturally (
'9'before'10'), blanks last. Column-field header labels use the source column'svalueFormatter(a boolean column formatted as Yes / No readsActive: Yes — Salary (sum)). -
Column rules. A row or column field on a
groupable: falsecolumn is skipped (as in row grouping), and a value field on anaggregable: falsecolumn, or whose function the column'savailableAggregationFunctionsdoes not allow, is skipped. Listing the same field and function twice produces one column. The toolbar's pivot panel offers only what these rules allow and never offers anaggregable: falsecolumn as a value. -
Column order. The generated columns keep an order of their own: reordering them (in the header or the Columns panel) does not change your column order, and a controlled
columnOrder(which names source columns) does not apply to them. When pivot mode is turned off, the previous column order is back.
- Tree data and row grouping are turned off while pivoting (the pivot rows are already grouped by the row fields). A development warning says so.
-
dataSource: pivoting is client-side, and a server-driven grid only holds one page of rows, sopivotModeis ignored when adataSourceis set (development warning). Pivot on the server, or pass the full dataset asrows. -
aggregationModel: the footer is not shown,apiRef.current.getAggregationResult()returnsnullandslots.footerreceivesaggregationResult: null; the Grand Total row is the pivot's aggregate. The toolbar's Summaries panel does not list generated pivot columns.
Built-in functions available (the same functions drive the footer, group rows, pivot and exports):
-
sum: Total of numeric values. -
avg: Arithmetic mean. -
min: Smallest value. -
max: Largest value. -
count: Number of non-empty values. -
unique: Number of distinct non-empty values.
sum, avg, min and max use numbers, numeric strings and dates. Empty values (null, undefined, and strings that are empty or only whitespace), booleans and other values are ignored, so a blank cell never counts as 0. count and unique ignore empty values too. min and max of dates return the date itself.
The toolbar's Summaries panel offers these for each aggregable column, or only the ones listed in the column's availableAggregationFunctions. The same rules bind aggregationModel itself: an entry for an aggregable: false column, or with a function the column does not allow, is ignored by the footer, group rows and exports.
The footer, group rows, pivot value cells and every export format aggregates the same way:
-
sum,avg,minandmaxgo through the column'svalueFormatter, so totals keep the column's currency, unit or percent format. The formatter'srowis the record of aggregated values: the footer totals, the group row, or the pivot row. A formatter that throws (typically because it reads row data an aggregate does not have) falls back to the default format instead of breaking the grid. -
countanduniqueare plain counts: the column'svalueFormatteris not applied (a count of a currency column is not an amount). - Without a formatter, numbers are locale-formatted (
avgto at most two decimals) and dates show as locale dates.
Exports follow the same rules; see Aggregate values. Use formatAggregationValue(value, fnName) for the default number formatting elsewhere.
OpenGridX 3.2.2 · MIT · This wiki is generated from docs/ on every push to main. To fix a page, open a PR against the source file.
Start here
Components
- DataGrid
- Header
- Row
- Cell
- Toolbar
- Pagination
- Filter Panel
- Tooltip
- Column Visibility
- Column Grouping
- Column Resizing
- Empty State
- Error Overlay
- Aggregation Footer
Features
- Virtualization
- Filtering & Search
- Sorting & Pagination
- Custom Pagination
- Editing & Reordering
- Row Selection
- Clipboard
- Pinning
- State Persistence
- Aggregation & Pivot
- Tree Data & Grouping
- Cell Spanning
- Master-Detail
- Keyboard & Accessibility
- List View
- Infinite Scroll
- Data Source
- Loading States
- Toolbar Customization
- Export (CSV, Excel, JSON, Print)
- PDF Export
Customization
Upgrading
Contributing
- Contributing
- Testing
- Roadmap
- DataGrid orchestration
- GridRowMeta
- useGridControlledState
- useGridRowPipeline
- useGridColumns
- useGridVirtualization
- useGridVisibleRows
- useGridScrollSync
- useGridStateSnapshot