Row Grouping in AG-Grid React: Organizing Your Data Hierarchically
Welcome to another installment in our AG-Grid React series! Today, we're diving deep into one of AG-Grid's most powerful features for data organization and analysis: Row Grouping. Row grouping allows you to transform a flat dataset into a hierarchical structure, making it incredibly easy to summarize, analyze, and navigate large volumes of data within your React applications.
Imagine you have a list of sales transactions. Instead of sifting through thousands of individual entries, row grouping lets you group them by `productCategory`, then by `region`, and finally display subtotals for each group. This level of aggregation and clarity is indispensable for dashboards and enterprise applications.
Understanding the Basics of Row Grouping
At its core, row grouping in AG-Grid allows you to collect rows that share a common value in a specified column into a single, collapsible group. This process creates a tree-like structure, where parent nodes represent the groups, and child nodes are the individual data rows or sub-groups.
Enabling Basic Row Grouping
To enable row grouping, you simply need to set the `rowGroup: true` property on the column definition(s) you wish to group by. AG-Grid will automatically create a new "group column" to display the group names and provide expand/collapse functionality.
Here’s how you can group data by a single column, for example, `country`:
import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { AgGridReact } from 'ag-grid-react';
import "ag-grid-community/styles/ag-grid.css";
import "ag-grid-community/styles/ag-theme-alpine.css";
const RowGroupingExample = () => {
const gridRef = useRef();
const [rowData, setRowData] = useState([]);
const columnDefs = useMemo(() => [
{ field: 'country', rowGroup: true, hide: true }, // Group by country, hide the original column
{ field: 'athlete' },
{ field: 'year', width: 90 },
{ field: 'gold', aggFunc: 'sum' }, // We'll look at aggFunc later
{ field: 'silver', aggFunc: 'sum' },
{ field: 'bronze', aggFunc: 'sum' }
], []);
const defaultColDef = useMemo(() => ({
flex: 1,
minWidth: 100,
resizable: true,
}), []);
useEffect(() => {
fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
.then(resp => resp.json())
.then(data => setRowData(data));
}, []);
return (
<div className="ag-theme-alpine" style={{ height: 500, width: '100%' }}>
<AgGridReact
ref={gridRef}
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
animateRows={true}
rowSelection="multiple"
/>
</div>
);
};
export default RowGroupingExample;
In this example, we set `rowGroup: true` for the `country` column. We also added `hide: true` to prevent the `country` column from appearing twice (once as the grouping column and once as a regular data column). AG-Grid will then automatically create a single group column (usually the first visible column) to display the grouped `country` values.
Grouping by Multiple Columns
You can easily group by multiple columns to create a more granular hierarchy. Simply set `rowGroup: true` on all the columns you want to group by. The order in which you define them in `columnDefs` typically determines the grouping order.
Let's extend our example to group by `country` and then by `year`:
const columnDefs = useMemo(() => [
{ field: 'country', rowGroup: true, hide: true },
{ field: 'year', rowGroup: true, hide: true }, // Group by year as well
{ field: 'athlete' },
{ field: 'gold', aggFunc: 'sum' },
{ field: 'silver', aggFunc: 'sum' },
{ field: 'bronze', aggFunc: 'sum' }
], []);
Now, your data will be grouped first by country, and within each country, it will be further grouped by year.
Customizing the Group Display Column with `autoGroupColumnDef`
When you enable row grouping, AG-Grid automatically generates a special column to display the group names and the expand/collapse icons. This column is referred to as the "auto group column". By default, it's often the first visible column, but you can explicitly define and customize it using the `autoGroupColumnDef` grid option.
The `autoGroupColumnDef` allows you to control many aspects of this column, such as its header name, cell renderer, style, and more.
const autoGroupColumnDef = useMemo(() => ({
headerName: 'Country & Year Group',
minWidth: 250,
cellRendererParams: {
// Suppress the checkbox for row selection inside the group header
// For general row selection, you'd configure rowSelection='multiple' on the grid
suppressCount: false, // Show row count next to group name
checkbox: true, // Add a checkbox for group selection (if rowSelection is enabled)
},
}), []);
// ... inside AgGridReact component
<AgGridReact
// ... other props
autoGroupColumnDef={autoGroupColumnDef}
/>
You can also use custom cell renderers within `autoGroupColumnDef.cellRenderer` to completely control how group names are displayed, adding icons, custom formatting, or even interactive elements.
Aggregating Data with `aggFunc`
One of the most powerful aspects of row grouping is the ability to perform aggregations on the grouped data. AG-Grid provides built-in aggregation functions and allows you to define custom ones.
Built-in Aggregation Functions
You can specify an `aggFunc` on any column definition that you want to aggregate. AG-Grid supports common functions like:
sum: Sums up the values.min: Finds the minimum value.max: Finds the maximum value.avg: Calculates the average.count: Counts the number of values (non-null, non-undefined).first: Returns the first value encountered.last: Returns the last value encountered.
const columnDefs = useMemo(() => [
{ field: 'country', rowGroup: true, hide: true },
{ field: 'year', rowGroup: true, hide: true },
{ field: 'athlete' },
{ field: 'gold', aggFunc: 'sum' }, // Sum gold medals per group
{ field: 'silver', aggFunc: 'sum' }, // Sum silver medals per group
{ field: 'bronze', aggFunc: 'sum' }, // Sum bronze medals per group
{ field: 'totalMedals', valueGetter: 'data.gold + data.silver + data.bronze', aggFunc: 'sum' }
], []);
When you expand a group, the aggregated values will be displayed in the respective columns for the group row. When a group is collapsed, these aggregated values will represent the total for that entire group.
Custom Aggregation Functions
For more complex aggregation logic, you can define your own `aggFunc`. This involves providing a function that takes an array of values for a specific column within a group and returns a single aggregated value.
const columnDefs = useMemo(() => [
// ... other column definitions
{
field: 'points',
aggFunc: (params) => {
let sum = 0;
params.values.forEach(value => {
if (typeof value === 'number') {
sum += value;
}
});
return sum;
},
headerName: 'Total Points',
}
], []);
Configuring Group Display Type with `groupDisplayType`
AG-Grid offers several ways to display grouped data using the `groupDisplayType` grid option. This is crucial for controlling the visual layout of your hierarchical data.
-
'singleColumn'(Default): Displays all group levels in a single auto-generated group column. This is the most common and compact display. -
'multipleColumns': Creates a new column for each level of grouping. For instance, if you group by `country` and `year`, you'll see a 'Country' group column and a 'Year' group column. This can make hierarchies clearer but uses more horizontal space. -
'groupRows': Displays group information across the full width of the grid, similar to master-detail rows but for groups. The group row itself spans all columns. -
'custom': Requires you to provide your own `autoGroupColumnDef` to fully control the group column's behavior and rendering.
Example of using `groupDisplayType`:
const RowGroupingExample = () => {
// ...
return (
<div className="ag-theme-alpine" style={{ height: 500, width: '100%' }}>
<AgGridReact
// ... other props
groupDisplayType="multipleColumns" // Try 'groupRows' or 'singleColumn'
/>
</div>
);
};
Programmatic Grouping and Initial State
You can control the initial grouping state programmatically rather than relying solely on user interaction. This is done via grid options like `groupDefaultExpanded` or by setting initial `rowGroup` properties on `defaultColDef`.
-
groupDefaultExpanded: Controls the default expansion state of all groups.0: All groups collapsed.1: First level of groups expanded.-1: All groups expanded.
-
sideBar: 'columns': Useful for allowing users to drag and drop columns into the group panel to dynamically change grouping.
const RowGroupingExample = () => {
// ...
const gridOptions = {
groupDefaultExpanded: 1, // Expand the first level of groups by default
// For enabling the Columns Tool Panel (Sidebar)
sideBar: {
toolPanels: ['columns'],
defaultToolPanel: 'columns'
}
};
return (
<div className="ag-theme-alpine" style={{ height: 500, width: '100%' }}>
<AgGridReact
// ... other props
gridOptions={gridOptions}
/>
</div>
);
};
Important Grouping Properties and Events
Here are a few other notable properties and events related to row grouping:
-
groupHideOpenParents: true: When true, if a group is expanded, its parent row is hidden. Useful when drilling down. -
suppressGroupSort: true: Prevents the group rows from being sorted. -
groupRowRenderer/groupRowRendererParams: For advanced custom rendering of group rows (when `groupDisplayType` is not 'singleColumn'). -
onRowGroupOpened(event): An event fired when a group is expanded or collapsed. You can use this to react to user interactions.
Conclusion
Row grouping is a fundamental feature of AG-Grid that elevates your data presentation and analysis capabilities in React applications. By transforming flat data into an intuitive, hierarchical view with powerful aggregation options, you provide users with a much richer and more manageable experience. Experiment with different `groupDisplayType` settings, custom `autoGroupColumnDef` configurations, and various `aggFunc` options to tailor the grouping behavior precisely to your application's needs.
Mastering row grouping is a significant step towards building highly interactive and data-driven grids. In the next parts of this series, we'll explore even more advanced AG-Grid features!