Skip to content
+

Data Grid - Row grouping

Group rows together based on column values in the Data Grid.

The Data Grid Premium provides a row grouping feature to create subsets of rows based on repeated column values or custom functions.

For example, in the demo below, movies are grouped based on their respective values in the Company column—try clicking the > on the left side of a row group to expand it:

Initializing row grouping

To initialize row grouping, provide a model to the initialState prop on the <DataGridPremium /> component. The model's parameters correspond to the columns to be checked for repeating values.

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

This example creates groups for the Company column with nested subgroups based on the Director column:

Controlled row grouping

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

Grouping columns

Single grouping column

By default, the Data Grid displays a single column that holds all grouped columns, no matter how many criteria are provided. If there's only one criterion, the name of the grouping column will be the same as that of the grouped column from which it's derived. When there are multiple criteria, the grouping column is named Group.

Multiple grouping columns

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

Custom grouping column

Use the groupingColDef prop to customize the rendering of the grouping column. You can override any property from the column definition (GridColDef) interface, with the exceptions of the field, the type, and the properties related to inline editing.

By default, when using the object format, the properties are applied to all grouping columns. This means that if rowGroupingColumnMode is set to multiple, then all columns will share the same groupingColDef properties.

To override properties for 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 parameters.

The demo below illustrates this approach to provide buttons for toggling between different grouping criteria:

Group by company
Group by company and director

Grouping rows with custom cell renderer

By default, when rows are grouped by a column that uses a custom cell component, that component is also used for the cells in the grouping column.

For example, the demo below groups together movies based on the values in the Rating column. Those cells contain a custom component with a star icon, and that same component is used to fill the grouping column.

You can opt out of this default behavior by returning params.value from the renderCell() function—this ensures that the grouping rows will only display the shared value rather than the entire component.

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

    return (
      // ...
    );
  },
};

Show values for leaves

By default, grouped rows display no value in their grouping column cells—these cells are called leaves. To display a value in a leaf, provide the leafField property to the groupingColDef.

The demo below uses leafField to display values from the Title column in the leaves.

Hide descendant count

By default, row group cells display the number of descendant rows they contain, in parentheses. Use the hideDescendantCount property of the groupingColDef to hide this number.

Hide grouped columns

By default, grouped columns remain visible when grouping is applied. This means that when there's only one grouping criterion, the grouping column and the grouped column both display the same values, which may be redundant or unnecessary. You can use the useKeepGroupedColumnsHidden utility hook to hide grouped columns. This automatically hides grouped columns when added to the model, and displays them when removed.

The two examples below show how to use columnVisibilityModel and initialState with the 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}
  />
);

Disable row grouping

For all columns

To disable row grouping for all columns, set the disableRowGrouping prop to true. This disables all features related to row grouping, unless a model is provided, in which case row grouping is set to read-only mode as described in Grouping non-groupable columns programmatically.

For specific columns

To disable grouping for a specific column, set the groupable property on its GridColDef to false.

In the example below, the Director column cannot be grouped, even though there are repeating values. (The Title and Gross columns cannot be grouped in any examples in this doc because there are no repeating values.)

Grouping non-groupable columns programmatically

To apply row grouping programmatically on non-groupable columns (columns with groupable: false in the GridColDef), you can provide the row grouping model in one of three ways:

  1. Pass rowGrouping.model to the initialState prop. This initializes grouping with the provided model.
  2. Provide the rowGroupingModel prop. This controls grouping with the provided model.
  3. Call the API method setRowGroupingModel. This sets the aggregation with the provided model.

In the following example, the Company column is not groupable through the interface, but the rowGroupingModel prop is passed to generate a read-only row group.

Using groupingValueGetter for complex grouping value

The grouping value must 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: (value) => value.name,
  },
  // ...
];

Rows with missing groups

If a grouping criterion's key is null or undefined for a given row, the Data Grid will treat that row as if it doesn't have a value and exclude it from grouping.

The demo below illustrates this behavior—movies are grouped by Cinematic Universe, and rows with no value for this column are displayed individually before those with values are displayed in groups:

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. To expand the whole tree, set defaultGroupingExpansionDepth = -1.

Use the isGroupExpandedByDefault() prop to expand groups by default according to more complex logic. This prop is a callback that receives a node as an argument. When defined, this callback always takes priority over the defaultGroupingExpansionDepth prop.

isGroupExpandedByDefault={
  node => node.groupingField === 'company' && node.groupingKey === '20th Century Fox'
}

The example below uses this pattern to render the Grid with the 20th Century Fox group expanded:

Use the setRowChildrenExpansion() method on the apiRef object to programmatically set the expansion of a row. Changing the expansion of a row emits a rowExpansionChange event that you can listen for to react to the expansion change.

The demo below uses this pattern to implement the expansion toggle button:

Customize grouping cell indent

Use the --DataGrid-cellOffsetMultiplier CSS variable to change the default cell indentation, as shown here:

<DataGridPremium
  sx={{
    // default value is 2
    '--DataGrid-cellOffsetMultiplier': 6,
  }}
/>

Sorting and filtering

Single grouping column

When using rowGroupingColumnMode = "single", the default behavior is to sort each grouping criterion using the column's sortComparator, then apply the filterOperators from the top-level grouping criteria.

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

You can force the filtering to be applied to other grouping criteria using the mainGroupingCriteria property of groupingColDef.

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're rendering leaves in one of those columns with the leafField property of groupingColDef, then sorting and filtering will be applied on the leaves for this grouping column based on the sortComparator and filterOperators of their 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 groupingColDef to be equal to the grouping criteria.

In the example below, sorting and filtering from the Company grouping column are applied to the company field, while sorting and filtering from the Director grouping column are applied to the director field even though it has leaves.

Automatic parent and child selection

By default, selecting a parent row also selects all of its descendants. You can customize this behavior using the rowSelectionPropagation prop. Here's how it's structured:

type GridRowSelectionPropagation = {
  descendants?: boolean; // default: true
  parents?: boolean; // default: true
};

When rowSelectionPropagation.descendants is set to true:

  • Selecting a parent selects all of its filtered descendants automatically
  • Deselecting a parent row deselects of all its filtered descendants automatically

When rowSelectionPropagation.parents is set to true:

  • Selecting all the filtered descendants of a parent also selects the parent automatically
  • Deselecting a descendant of a selected parent also deselects the parent automatically

The example below demonstrates the usage of the rowSelectionPropagation prop—use the checkboxes at the top to see how the selection behavior changes between parents and children.

Row selection propagation also affects the Select all checkbox like any other checkbox group. Selected rows that do not pass the filtering criteria are automatically deselected when the filter is applied. Row selection propagation is not applied to the unfiltered rows.

Get all rows in a group

Use the apiRef.current.getRowGroupChildren() method to get the IDs of all rows in a group. The results will not contain autogenerated rows such as subgroup rows or 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,
});

Use getGroupRowIdFromPath() to get row IDs from within all groups that match a given grouping criterion:

const rows = apiRef.current.getRowGroupChildren({
  groupId: getGroupRowIdFromPath([{ field: 'company', key: 'Disney Studios' }]),
});

Row group panel 🚧

With the row group panel, users would be able to control which columns are used for grouping by dragging them inside the panel.

Advanced use cases

The demo below provides an example of row grouping that's closer to a real-world use case for this feature, grouping a large dataset of contacts based on the types of goods they provide (via the hidden Commodity column).

See Row grouping recipes for more advanced use cases.

apiRef

The Data Grid exposes a set of methods via the apiRef object that are used in the implementation of the row grouping feature. The reference below describes the relevant functions. See API object for more details.

Signature:
addRowGroupingCriteria: (groupingCriteriaField: string, groupingIndex?: number) => void

Signature:
removeRowGroupingCriteria: (groupingCriteriaField: string) => void

Signature:
setRowGroupingCriteriaIndex: (groupingCriteriaField: string, groupingIndex: number) => void

Signature:
setRowGroupingModel: (model: GridRowGroupingModel) => void