Skip to content

Data Grid - Group & Pivot

Use grouping, pivoting, and more to analyze the data in depth.

Row grouping

For when you need to group rows based on repeated column values, and/or custom functions. On the following example, we're grouping all movies based on their production company

โš ๏ธ This feature is temporarily available on the Pro plan until the release of the Premium plan.

To avoid future regression for users of the Pro plan, the feature needs to be explicitly activated using the rowGrouping experimental feature flag.

<DataGridPro experimentalFeatures={{ rowGrouping: true }} {...otherProps} />

The feature is stable in its current form, and we encourage users willing to migrate to the Premium plan once available to start using it.

Set grouping criteria

Initialize the row grouping

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

initialState={{
    rowGrouping: {
        model: ['company', 'director'],
    }
}}

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

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 page size and update the prop accordingly.

Grouping columns

Single grouping column

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

Multiple grouping column

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

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.

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

Show values for the leaves

By default, the grouped rows display no value on their grouping columns' cells. We're calling those cells "leaves".

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

Hide the descendant count

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

Disable the row grouping

For all columns

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

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

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.

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: GridColumns = [
  {
    field: 'composer',
    groupingValueGetter: (params) => params.value.name,
  },
  // ...
];

Note: If your column also have a valueGetter property, the value passed to the groupingValueGetter method will still be the row value from the row[field].

Rows with missing groups

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

Group expansion

By default, all groups are initially displayed collapsed. You can change this behaviour 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

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 the priority over the defaultGroupingExpansionDepth prop.

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

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

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

โš ๏ธ This feature is not yet compatible with sortingMode = "server and filteringMode = "server"

Multiple grouping column

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

โš ๏ธ If you are dynamically switching the leafField or mainGroupingCriteria, the sorting and filtering models will not automatically be cleaned-up and the sorting / filtering will not be re-applied.

Full example

apiRef

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

Tree Data

Tree Data allows to display data with parent/child relationships.

To enable the Tree Data, you simply have to use the treeData prop as well as provide a getTreeDataPath prop. The getTreeDataPath function returns an array of strings which represents the path to a given row.

// The following examples will both render the same tree
// - Sarah
//     - Thomas
//         - Robert
//         - Karen

const columns: GridColumns = [{ field: 'jobTitle', width: 250 }];

// Without transformation
const rows: GridRowsProp = [
  { path: ['Sarah'], jobTitle: 'CEO', id: 0 },
  { path: ['Sarah', 'Thomas'], jobTitle: 'Head of Sales', id: 1 },
  { path: ['Sarah', 'Thomas', 'Robert'], jobTitle: 'Sales Person', id: 2 },
  { path: ['Sarah', 'Thomas', 'Karen'], jobTitle: 'Sales Person', id: 3 },
];

<DataGridPro
  treeData
  getTreeDataPath={(row) => row.path}
  rows={rows}
  columns={columns}
/>;

// With transformation
const rows: GridRowsProp = [
  { path: 'Sarah', jobTitle: 'CEO', id: 0 },
  { path: 'Sarah/Thomas', jobTitle: 'Head of Sales', id: 1 },
  { path: 'Sarah/Thomas/Robert', jobTitle: 'Sales Person', id: 2 },
  { path: 'Sarah/Thomas/Karen', jobTitle: 'Sales Person', id: 3 },
];

<DataGridPro
  treeData
  getTreeDataPath={(row) => row.path.split('/')}
  rows={rows}
  columns={columns}
/>;

Custom grouping column

Same behavior as for the Row grouping except for the leafField and mainGroupingCriteria which are not applicable for the Tree Data.

Accessing the grouping column field

If you want to access the grouping column field, for instance, to use it with column pinning, the GRID_TREE_DATA_GROUPING_FIELD constant is available.

<DataGridPro
  treeData
  initialState={{
    pinnedColumns: {
      left: [GRID_TREE_DATA_GROUPING_FIELD],
    },
  }}
  {...otherProps}
/>

Group expansion

Same behavior as for the Row grouping.

Gaps in the tree

If some entries are missing to build the full tree, the DataGridPro will automatically create rows to fill those gaps.

Filtering

A node is included if one of the following criteria is met:

  • at least one of its descendant is passing the filters
  • it is passing the filters

By default, the filtering is applied to every depth of the tree. You can limit the filtering to the top-level rows with the disableChildrenFiltering prop.

Sorting

By default, the sorting is applied to every depth of the tree. You can limit the sorting to the top level rows with the disableChildrenSorting prop.

If you are using sortingMode="server", you need to always put the children of a row after its parent. For instance:

// โœ… The row A.A is immediately after its parent
const validRows = [{ path: ['A'] }, { path: ['A', 'A'] }, { path: ['B'] }];

// โŒ The row A.A is not immediately after its parent
const invalidRows = [{ path: ['A'] }, { path: ['B'] }, { path: ['A', 'A'] }];

Children lazy-loading

โš ๏ธ This feature isn't implemented yet. It's coming.

๐Ÿ‘ Upvote issue #3377 if you want to see it land faster.

Alternatively, you can achieve a similar behavior by implementing this feature outside the component as shown bellow. This implementation does not support every feature of the grid but can be a good starting point for large datasets.

The idea is to add a property descendantCount on the row and to use it instead of the internal grid state. To do so, we need to override both the renderCell of the grouping column and to manually open the rows by listening to GridEvents.rowExpansionChange.

Full example

๐Ÿšง Master detail

โš ๏ธ This feature isn't implemented yet. It's coming.

๐Ÿ‘ Upvote issue #211 if you want to see it land faster.

The feature allows to display row details on an expandable pane.

๐Ÿšง Aggregation

โš ๏ธ This feature isn't implemented yet. It's coming.

๐Ÿ‘ Upvote issue #213 if you want to see it land faster.

When grouping, you will be able to apply an aggregation function to populate the group row with values.

๐Ÿšง Pivoting

โš ๏ธ This feature isn't implemented yet. It's coming.

๐Ÿ‘ Upvote issue #214 if you want to see it land faster.

Pivoting will allow you to take a columns values and turn them into columns.

API