Skip to content

Data Grid - Row grouping

Group your rows according to some column values.

For when you need to group rows based on repeated column values, and/or custom functions. In the following example, movies are grouped based on their production company:

Company
Title
Gross
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Grouping criteria

Initialize the row grouping

The easiest way to get started with the feature is to provide its model to the initialState prop:

<DataGridPremium
  initialState={{
    rowGrouping: {
      model: ['company', 'director'],
    },
  }}
/>

The basic parameters are the columns you want to check for repeating values. This example groups all the movies matching the same company name, followed by a second group matching the director's name.

Group
Title
Gross
Company
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Controlled row grouping

If you need to control the state of the criteria used for grouping, use the rowGroupingModel prop. You can use the onRowGroupingModelChange prop to listen to changes to the grouping criteria and update the prop accordingly.

Group
Title
Gross
Company
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Grouping columns

Single grouping column

By default, the data grid will display a single column holding all grouping columns. If you have multiple grouping criteria, this column name will be set to "Group."

Group
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Multiple grouping columns

To display a column for each grouping criterion, set the rowGroupingColumnMode prop to multiple.

Company
Director
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Custom grouping column

To customize the rendering of the grouping column, use the groupingColDef prop. You can override the headerName or any property of the GridColDef interface, except the field, the type, and the properties related to inline edition.

Group
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

By default, when using the object format, the properties will be applied to all Grouping columns. This means that if you have rowGroupingColumnMode set to multiple, all the columns will share the same groupingColDef properties.

If you wish to override properties of specific grouping columns or to apply different overrides based on the current grouping criteria, you can pass a callback function to groupingColDef, instead of an object with its config. The callback is called for each grouping column, and it receives the respective column's "fields" as parameter.

Group by company
Group by company and director
Director
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Grouping rows with custom cell renderer

By default, when rows are grouped by a column with a custom cell component (GridColDef['renderCell']), the same custom cell component is used in the grouping column.

Rating
Title
Gross
Company
Director
Year
Cinematic Universe
7.9/10
(3)
8.4/10
(3)
8.5/10
(1)
8.3/10
(2)
7/10
(1)
6.9/10
(2)
8.1/10
(1)
7.2/10
(2)
Total Rows: 23

You can opt out of this default behavior by returning params.value in renderCell for grouping rows instead:

const ratingColDef: GridColDef = {
  // ...
  renderCell: (params) => {
    if (params.rowNode.type === 'group') {
      return params.value;
    }

    return (
      // ...
    );
  },
};
Rating
Title
Gross
Company
Director
Year
Cinematic Universe
7.9 (3)
8.4 (3)
8.5 (1)
8.3 (2)
7 (1)
6.9 (2)
8.1 (1)
7.2 (2)
Total Rows: 23

Show values for the leaves

By default, the grouped rows display no value on their grouping columns' cells. Those cells are called "leaves."

If you want to display some value, you can provide a leafField property to the groupingColDef.

Title
Gross
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Hide the descendant count

Use the hideDescendantCount property of the groupingColDef to hide the number of descendants of a grouping row.

Company
Title
Gross
Director
Year
Cinematic Universe
20th Century Fox
Disney Studios
Universal Pictures
Warner Bros. Pictures
New Line Cinema
Paramount Pictures
Total Rows: 6

Hide the grouped columns

By default, the columns used to group the rows remains visible. For instance if you group by "director", you have two columns titled Director:

  • The grouped column (the column from which you grouped the rows)
  • The grouping column on which you can toggle the groups

To automatically hide the grouped columns, use the useKeepGroupedColumnsHidden utility hook. The hook automatically hides the columns when added to the model, and displays them when removed from it.

Below are two examples about how to use columnVisibilityModel or initialState with useKeepGroupedColumnsHidden hook. You can mix the two examples to support both at the same time.

// Usage with the initial state
const apiRef = useGridApiRef();

const initialState = useKeepGroupedColumnsHidden({
  apiRef,
  initialState: {
    rowGrouping: {
      model: ['company'],
    },
    columns: {
      // Other hidden columns
      columnVisibilityModel: { gross: false },
    },
  },
});

return <DataGridPremium {...data} apiRef={apiRef} initialState={initialState} />;
// Usage with the controlled model
const apiRef = useGridApiRef();

const [rowGroupingModel, setRowGroupingModel] = React.useState([
  'company',
  'director',
]);

const initialState = useKeepGroupedColumnsHidden({
  apiRef,
  rowGroupingModel,
});

return (
  <DataGridPremium
    {...data}
    apiRef={apiRef}
    initialState={initialState}
    rowGroupingModel={rowGroupingModel}
  />
);
Company
Title
Gross
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Disable the row grouping

For all columns

You can disable row grouping by setting the disableRowGrouping prop to true.

It will disable all the features related to the row grouping, even if a model is provided.

Title
Gross
Company
Director
Year
Cinematic Universe
Avatar
$2,847,246,203
20th Century Fox
James Cameron
2,009
Avengers: Endgame
$2,797,501,328
Disney Studios
Anthony & Joe Russo
2,019
Marvel Cinematic Universe
Titanic
$2,187,425,379
20th Century Fox
James Cameron
1,997
Star Wars: The Force Awakens
$2,068,223,624
Disney Studios
J. J. Abrams
2,015
Star Wars
Avengers: Infinity War
$2,048,359,754
Disney Studios
Anthony & Joe Russo
2,018
Marvel Cinematic Universe
Spider-Man: No Way Home
$1,892,768,346
Disney Studios
Jon Watts
2,021
Marvel Cinematic Universe
Jurassic World
$1,671,713,208
Universal Pictures
Colin Trevorrow
2,015
Jurassic Park
The Lion King
$1,656,943,394
Disney Studios
Jon Favreau
2,019
The Avengers
$1,518,812,988
Disney Studios
Joss Whedon
2,012
Marvel Cinematic Universe
Total Rows: 35

For some columns

In case you need to disable grouping on specific column(s), set the groupable property on the respective column definition (GridColDef) to false. In the example below, the director column can not be grouped. And in all example, the title and gross columns can not be grouped.

Company
Title
Gross
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Using groupingValueGetter for complex grouping value

The grouping value has to be either a string, a number, null, or undefined. If your cell value is more complex, pass a groupingValueGetter property to the column definition to convert it into a valid value.

const columns: GridColDef[] = [
  {
    field: 'composer',
    groupingValueGetter: (params) => params.value.name,
  },
  // ...
];
Group
Title
Gross
Company
Director
Year
Cinematic Universe
James Horner (2)
Alan Silvestri (3)
John Williams (3)
Michael Giacchino (5)
Hans Zimmer (2)
Brian Tyler (3)
Christophe Beck (2)
Danny Elfman (1)
Ludwig Göransson (1)
Total Rows: 20

Rows with missing groups

If the grouping key of a grouping criteria is null or undefined for a row, the data grid will consider that this row does not have a value for this group. and will inline it for those groups.

Cinematic Universe
Title
Gross
Company
Director
Year
Avatar
$2,847,246,203
20th Century Fox
James Cameron
2,009
Titanic
$2,187,425,379
20th Century Fox
James Cameron
1,997
The Lion King
$1,656,943,394
Disney Studios
Jon Favreau
2,019
Beauty and the Beast
$1,263,521,136
Disney Studios
Bill Condon
2,017
Incredibles 2
$1,242,805,359
Disney Studios
Brad Bird
2,018
Minions
$1,159,398,397
Universal Pictures
Pierre Coffin & Kyle Balda
2,015
Marvel Cinematic Universe (10)
Star Wars (3)
Jurassic Park (2)
Total Rows: 18

Group expansion

By default, all groups are initially displayed collapsed. You can change this behavior by setting the defaultGroupingExpansionDepth prop to expand all the groups up to a given depth when loading the data. If you want to expand the whole tree, set defaultGroupingExpansionDepth = -1

Group
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
James Cameron (2)
Avatar
$2,847,246,203
2,009
Titanic
$2,187,425,379
1,997
Sam Mendes (1)
Skyfall
$1,108,561,013
2,012
James Bond
Disney Studios (20)
Anthony & Joe Russo (3)
Avengers: Endgame
$2,797,501,328
2,019
Marvel Cinematic Universe
Total Rows: 6

If you want to expand groups by default according to a more complex logic, use the isGroupExpandedByDefault prop which is a callback receiving the node as an argument. When defined, this callback will always have priority over the defaultGroupingExpansionDepth prop.

isGroupExpandedByDefault={
  node => node.groupingField === 'company' && node.groupingKey === '20th Century Fox'
}
Group
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
James Cameron (2)
Sam Mendes (1)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Use the setRowChildrenExpansion method on apiRef to programmatically set the expansion of a row.

Company
Title
Gross
Director
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6

Customize grouping cell indent

To change the default cell indent you can pass the offsetMultiplier prop to the <GridTreeDataGroupingCell /> component and use it as groupingColDef.renderCell:

const groupingColDef = {
  renderCell: (params) => (
    <GridTreeDataGroupingCell {...params} offsetMultiplier={4} />
  ),
};

<DataGridPremium groupingColDef={groupingColDef} />;

Sorting / Filtering

Single grouping column

When using rowGroupingColumnMode = "single", the default behavior is to apply the sortComparator and filterOperators of the top-level grouping criteria.

If you are rendering leaves with the leafField property of groupColDef, the sorting and filtering will be applied on the leaves based on the sortComparator and filterOperators of their original column.

In both cases, you can force the sorting and filtering to be applied on another grouping criteria with the mainGroupingCriteria property of groupColDef

Group
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
James Cameron (2)
Avatar
$2,847,246,203
2,009
Titanic
$2,187,425,379
1,997
Sam Mendes (1)
Skyfall
$1,108,561,013
2,012
James Bond
Disney Studios (20)
Anthony & Joe Russo (3)
Avengers: Endgame
$2,797,501,328
2,019
Marvel Cinematic Universe
Total Rows: 6

Multiple grouping columns

When using rowGroupingColumnMode = "multiple", the default behavior is to apply the sortComparator and filterOperators of the grouping criteria of each grouping column.

If you are rendering leaves on one of those columns with the leafField property of groupColDef, the sorting and filtering will be applied on the leaves for this grouping column based on the sortComparator and filterOperators of the leave's original column.

If you want to render leaves but apply the sorting and filtering on the grouping criteria of the column, you can force it by setting the mainGroupingCriteria property groupColDef to be equal to the grouping criteria.

In the example below:

  • the sorting and filtering of the company grouping column is applied on the company field
  • the sorting and filtering of the director grouping column is applied on the director field even though it has leaves
Company
Director
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
James Cameron (2)
Avatar
Avatar
$2,847,246,203
2,009
Titanic
Titanic
$2,187,425,379
1,997
Sam Mendes (1)
Skyfall
Skyfall
$1,108,561,013
2,012
James Bond
Disney Studios (20)
Anthony & Joe Russo (3)
Avengers: Endgame
Avengers: Endgame
$2,797,501,328
2,019
Marvel Cinematic Universe
Total Rows: 6

Get the rows in a group

You can use the apiRef.current.getRowGroupChildren method to get the id of all rows contained in a group. It will not contain the autogenerated rows (i.e. the subgroup rows or the aggregation footers).

const rows: GridRowId[] = apiRef.current.getRowGroupChildren({
  groupId: params.id,

  // If true, the rows will be in the order displayed on screen
  applySorting: true,

  // If true, only the rows matching the current filters will be returned
  applyFiltering: true,
});

If you want to get the row ids of a group given its grouping criteria, use getGroupRowIdFromPath

const rows = apiRef.current.getRowGroupChildren({
  groupId: getGroupRowIdFromPath([{ field: 'company', key: 'Disney Studios' }]),
});
Group
Title
Gross
Year
Cinematic Universe
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)

🚧 Row group panel

With this panel, your users will be able to control which columns are used for grouping just by dragging them inside the panel.

Full example

Trader Email
Desk
Trader Name
Trader Email
Quantity
Filled Quantity
Is Filled
Status

Advanced use cases

See Row grouping recipes for more advanced use cases.

apiRef

The grid exposes a set of methods that enables all of these features using the imperative apiRef. To know more about how to use it, check the API Object section.

Signature:
addRowGroupingCriteria: (groupingCriteriaField: string, groupingIndex?: number) => void
Signature:
removeRowGroupingCriteria: (groupingCriteriaField: string) => void
Signature:
setRowGroupingCriteriaIndex: (groupingCriteriaField: string, groupingIndex: number) => void
Signature:
setRowGroupingModel: (model: GridRowGroupingModel) => void