Skip to content

Data grid - Aggregation

Use aggregation functions to combine your row values.

You can aggregate rows through the grid interface by opening the column menu and selecting from the items under Aggregation.

The aggregated values will be rendered in a footer row at the bottom of the grid.

Title
Gross
sum
Avatar
$2,847,246,203
Avengers: Endgame
$2,797,501,328
Titanic
$2,187,425,379
Star Wars: The Force Awakens
$2,068,223,624
Avengers: Infinity War
$2,048,359,754
Spider-Man: No Way Home
$1,892,768,346
Jurassic World
$1,671,713,208
The Lion King
$1,656,943,394
The Avengers
$1,518,812,988
Total Rows: 35

Pass aggregation to the grid

Structure of the model

The aggregation model is an object. The keys correspond to the columns, and the values are the name of the aggregation functions to use.

Initialize aggregation

To initialize aggregation without controlling its state, provide the model to the initialState prop.

Title
Gross
sum
Avatar
$2,847,246,203
Avengers: Endgame
$2,797,501,328
Titanic
$2,187,425,379
Star Wars: The Force Awakens
$2,068,223,624
Avengers: Infinity War
$2,048,359,754
Spider-Man: No Way Home
$1,892,768,346
Jurassic World
$1,671,713,208
The Lion King
$1,656,943,394
The Avengers
$1,518,812,988
Total Rows: 35
Press Enter to start editing

Controlled aggregation

Use the aggregationModel prop to control aggregation passed to the grid.

You can use the onAggregationModelChange prop to listen to changes to aggregation and update the prop accordingly.

Title
Gross
sum
Avatar
$2,847,246,203
Avengers: Endgame
$2,797,501,328
Titanic
$2,187,425,379
Star Wars: The Force Awakens
$2,068,223,624
Avengers: Infinity War
$2,048,359,754
Spider-Man: No Way Home
$1,892,768,346
Jurassic World
$1,671,713,208
The Lion King
$1,656,943,394
The Avengers
$1,518,812,988
Total Rows: 35
Press Enter to start editing

Disable aggregation

For all columns

You can disable aggregation by setting the disableAggregation prop to true.

It will disable all features related to aggregation, 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 aggregation on specific column(s), set the aggregable property on the respective column definition (GridColDef) to false. In the example below, the title and year columns are blocked from being aggregated:

Title
Gross
sum
Year
Avatar
$2,847,246,203
2,009
Avengers: Endgame
$2,797,501,328
2,019
Titanic
$2,187,425,379
1,997
Star Wars: The Force Awakens
$2,068,223,624
2,015
Avengers: Infinity War
$2,048,359,754
2,018
Spider-Man: No Way Home
$1,892,768,346
2,021
Jurassic World
$1,671,713,208
2,015
The Lion King
$1,656,943,394
2,019
The Avengers
$1,518,812,988
2,012
Total Rows: 35

Usage with row grouping

When the row grouping is enabled, the aggregated values will be displayed in two places:

  1. On the grouping rows - the grid will display each group aggregated value on its grouping row

  2. On the top-level footer - the grid will add a top-level footer to aggregate all the rows, as it would with a flat row list

Company
Title
Gross
sum
20th Century Fox (3)
$6,143,232,595
Disney Studios (20)
$29,154,440,516
Universal Pictures (5)
$6,895,406,742
Warner Bros. Pictures (4)
$4,645,905,239
New Line Cinema (1)
$1,146,030,912
Paramount Pictures (2)
$2,227,848,151
Total Rows: 6

You can customize this behavior using the getAggregationPosition prop.

This function takes the current group node as an argument (null for the root group) and returns the position of the aggregated value. This position must be one of the three following values:

  1. "footer" - the grid will add a footer to the group to aggregate its rows

  2. "inline" - the grid will disable aggregation on the grouping row

  3. null - the grid will not aggregate the group

// Will aggregate the root group on the top-level footer and the other groups on their grouping row
// (default behavior)
getAggregationPosition=(groupNode) => (groupNode == null ? 'footer' : 'inline'),

// Will aggregate all the groups on their grouping row
// The root will not be aggregated
getAggregationPosition={(groupNode) => groupNode == null ? null : 'inline'}

// Will only aggregate the company groups on the grouping row
// Director groups and the root will not be aggregated
getAggregationPosition={(groupNode) => groupNode?.groupingField === 'company' ? 'inline' : null}

// Will only aggregate the company group "Universal Pictures" on the grouping row
getAggregationPosition={(groupNode) =>
(groupNode?.groupingField === 'company' &&
  groupNode?.groupingKey === 'Universal Pictures') ? 'inline' : null
}

// Will only aggregate the root group on the top-level footer
getAggregationPosition={(groupNode) => groupNode == null ? 'footer' : null}

The demo below shows the sum aggregation on the footer of each group but not on the top-level footer:

Group
Title
Gross
sum
20th Century Fox (3)
Disney Studios (20)
Universal Pictures (5)
Warner Bros. Pictures (4)
New Line Cinema (1)
Paramount Pictures (2)
Total Rows: 6
Press Enter to start editing

Usage with tree data

As with row grouping, you can display the aggregated values either in the footer or in the grouping row.

The demo below shows the sum aggregation on the Size column and the max aggregation on the Last modification column.

Files
Size
sum
Last modification
max
.gitignore
0.4 Kb
4/8/2022, 7:29:49 AM
README.md
1.6 Kb
4/11/2022, 8:05:44 AM
next-env.d.ts
0.2 Kb
3/28/2022, 11:53:29 AM
next.config.js
88 b
3/28/2022, 11:53:29 AM
package.json
0.7 Kb
3/28/2022, 11:53:29 AM
tsconfig.json
0.5 Kb
3/28/2022, 11:53:29 AM
pages (4)
5.7 Kb
3/28/2022, 11:53:29 AM
public (1)
25.9 Kb
3/28/2022, 11:53:29 AM
src (5)
4.8 Kb
4/8/2022, 7:29:49 AM
Total Rows: 9

Filtering

By default, aggregation only uses the filtered rows. You can set the aggregationRowsScope to "all" to use all rows.

In the example below, the movie Avatar is not passing the filters but is still used for the max aggregation of the gross column.

Title
Gross
max
Titanic
$2,187,425,379
Total Rows: 1 of 35

Aggregation functions

Basic structure

An aggregation function is an object describing how to combine a given set of values.

const minAgg: GridAggregationFunction<number | Date> = {
  // Aggregates the `values` into a single value.
  apply: ({ values }) => Math.min(...values.filter((value) => value != null)),
  // This aggregation function is only compatible with numerical values.
  columnTypes: ['number'],
};

The full typing details can be found on the GridAggregationFunction API page.

Built-in functions

The @mui/x-data-grid-premium package comes with a set of built-in aggregation functions to cover the basic use cases:

Name Behavior Supported column types
sum Returns the sum of all values in the group number
avg Returns the non-rounded average of all values in the group number
min Returns the smallest value of the group number, date, dateTime
max Returns the largest value of the group number, date, dateTime
size Returns the amount of cells in the group all

Remove a built-in function

Remove a built-in function for all columns

You can remove some aggregation functions for all columns by passing a filtered object to the aggregationFunctions prop.

In the example below, the sum aggregation function has been removed:

Title
Gross
max
Avatar
$2,847,246,203
Avengers: Endgame
$2,797,501,328
Titanic
$2,187,425,379
Star Wars: The Force Awakens
$2,068,223,624
Avengers: Infinity War
$2,048,359,754
Spider-Man: No Way Home
$1,892,768,346
Jurassic World
$1,671,713,208
The Lion King
$1,656,943,394
The Avengers
$1,518,812,988
Total Rows: 35

Remove a built-in function for one column

You can limit the aggregation options in a given column by passing the availableAggregationFunctions property to the column definition.

This lets you specify which options will be available, as shown below:

const column = {
  field: 'year',
  type: 'number',
  availableAggregationFunctions: ['max', 'min'],
};

In the example below, the Year column can be aggregated using the max and min functions, whereas all functions are available for the Gross column:

Title
Gross
max
Year
max
Avatar
$2,847,246,203
2,009
Avengers: Endgame
$2,797,501,328
2,019
Titanic
$2,187,425,379
1,997
Star Wars: The Force Awakens
$2,068,223,624
2,015
Avengers: Infinity War
$2,048,359,754
2,018
Spider-Man: No Way Home
$1,892,768,346
2,021
Jurassic World
$1,671,713,208
2,015
The Lion King
$1,656,943,394
2,019
The Avengers
$1,518,812,988
2,012
Total Rows: 35
Press Enter to start editing

Create custom functions

You can pass custom aggregation functions to the aggregationFunctions prop.

An aggregation function is an object with the following shape:

const firstAlphabeticalAggregation: GridAggregationFunction<string, string | null> =
  {
    // The `apply` method takes the values to aggregate and returns the aggregated value
    apply: (params) => {
      if (params.values.length === 0) {
        return null;
      }

      const sortedValue = params.values.sort((a = '', b = '') => a.localeCompare(b));

      return sortedValue[0];
    },
    // The `label` property defines the label displayed in the column header when this aggregation is being used.
    label: 'firstAlphabetical',
    // The `types` property defines which type of columns can use this aggregation function.
    // Here, we only want to propose this aggregation function for `string` columns.
    // If not defined, aggregation will be available for all column types.
    columnTypes: ['string'],
  };

In the example below, the grid has two additional custom aggregation functions for string columns—firstAlphabetical and lastAlphabetical:

Title
Director
first alphabetical
Gross
Avatar
James Cameron
$2,847,246,203
Avengers: Endgame
Anthony & Joe Russo
$2,797,501,328
Titanic
James Cameron
$2,187,425,379
Star Wars: The Force Awakens
J. J. Abrams
$2,068,223,624
Avengers: Infinity War
Anthony & Joe Russo
$2,048,359,754
Spider-Man: No Way Home
Jon Watts
$1,892,768,346
Jurassic World
Colin Trevorrow
$1,671,713,208
The Lion King
Jon Favreau
$1,656,943,394
The Avengers
Joss Whedon
$1,518,812,988
Total Rows: 35

Aggregating data from multiple row fields

By default, the apply method of the aggregation function receives an array of values that represent a single field value of each row. For example, the sum aggregation function receives the values of the gross field.

In the example below, the values in the profit column are derived from the gross and budget fields of the row:

{
  field: 'profit',
  type: 'number',
  valueGetter: ({ row }) => {
    if (!row.gross || !row.budget) {
      return null;
    }
    return (row.gross - row.budget) / row.budget;
  }
}

To aggregate the profit column, you have to calculate the sum of the gross and budget fields separately, and then use the formula from the example above to calculate the aggregated profit value.

To do so, use the getCellValue callback on the aggregation function to transform the data that are being passed to the apply method:

const profit: GridAggregationFunction<{ gross: number; budget: number }, number> = {
  label: 'profit',
  getCellValue: ({ row }) => ({ budget: row.budget, gross: row.gross }),
  apply: ({ values }) => {
    let budget = 0;
    let gross = 0;
    values.forEach((value) => {
      if (value) {
        gross += value.gross;
        budget += value.budget;
      }
    });
    return (gross - budget) / budget;
  },
  columnTypes: ['number'],
};
Company
Title
Profit
profit
Gross
sum
Budget
sum
20th Century Fox (3)
864%
$6,143,232,595
$637,000,000
Disney Studios (20)
540%
$29,154,440,516
$4,557,000,000
Universal Pictures (5)
727%
$6,895,406,742
$834,000,000
Warner Bros. Pictures (4)
687%
$4,645,905,239
$590,000,000
New Line Cinema (1)
1119%
$1,146,030,912
$94,000,000
Paramount Pictures (2)
450%
$2,227,848,151
$405,000,000
Total Rows: 6

Custom value formatter

By default, the aggregated cell uses the value formatter of its column. But for some columns, the format of the aggregated value may have to differ from the format of the other cell values.

You can provide a valueFormatter method to your aggregation function to override the column's default formatting.

const aggregationFunction: GridAggregationFunction = {
  apply: () => {
    /* */
  },
  valueFormatter: (params) => {
    /* format the aggregated value */
  },
};
Title
Director
first alphabetical
Gross
Avatar
James Cameron
$2,847,246,203
Avengers: Endgame
Anthony & Joe Russo
$2,797,501,328
Titanic
James Cameron
$2,187,425,379
Star Wars: The Force Awakens
J. J. Abrams
$2,068,223,624
Avengers: Infinity War
Anthony & Joe Russo
$2,048,359,754
Spider-Man: No Way Home
Jon Watts
$1,892,768,346
Jurassic World
Colin Trevorrow
$1,671,713,208
The Lion King
Jon Favreau
$1,656,943,394
The Avengers
Joss Whedon
$1,518,812,988
Total Rows: 35

Custom rendering

If the column used to display aggregation has a renderCell property, the aggregated cell will call it with a params.aggregation object to let you decide how you want to render it.

This object contains a hasCellUnit which lets you know if the current aggregation has the same unit as the rest of the column's data—for instance, if your column is in $, is the aggregated value is also in $?

In the example below, you can see that all the aggregation functions are rendered with the rating UI aside from size, because it's not a valid rating:

Title
Rating
avg
The Lord of the Rings: The Return of the King
Avengers: Infinity War
Avengers: Endgame
The Dark Knight Rises
Joker
Spider-Man: No Way Home
Toy Story 3
Harry Potter and the Deathly Hallows – Part 2
The Avengers
Total Rows: 35

Selectors

Signature:
gridAggregationLookupSelector: (apiRef: GridApiRef) => GridAggregationLookup
// or
gridAggregationLookupSelector: (state: GridState, instanceId?: number) => GridAggregationLookup
Example
gridAggregationLookupSelector(apiRef)
// or
gridAggregationLookupSelector(state, apiRef.current.instanceId)
Signature:
gridAggregationModelSelector: (apiRef: GridApiRef) => GridAggregationModel
// or
gridAggregationModelSelector: (state: GridState, instanceId?: number) => GridAggregationModel
Example
gridAggregationModelSelector(apiRef)
// or
gridAggregationModelSelector(state, apiRef.current.instanceId)