Column Grouping Feature Guide
Material React Table has built-in column grouping features. There are options for both automatic client-side grouping as well as manual server-side grouping. This guide will walk you through the different options and how to use and customize them.
Relevant Table Options
# | Prop Name | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
|
| MRT Expanding Sub Rows Docs | ||
2 |
| MRT Aggregation and Grouping Docs | |||
3 |
| TanStack Table Grouping Docs | |||
4 |
|
| TanStack Table Grouping Docs | ||
5 |
| TanStack Table Grouping Docs | |||
6 |
| Material UI Chip Props | |||
7 |
| TanStack Table Grouping Docs | |||
8 |
|
| |||
9 |
| ||||
Relevant Column Options
Relevant State
# | State Option | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
|
| TanStack Table Expanding Docs | ||
2 |
|
| TanStack Table Grouping Docs | ||
Enable Grouping
To enable grouping, set the enableGrouping
table option to true
. This will both add a drag handle button so that columns can be dragged to the dropzone to be grouped and will add an entry column actions menu to group or ungroup a column.
const table = useMaterialReactTable({columns,data,enableGrouping: true,});
Grouped Column Mode
New in v2.5.0, The
"remove"
columnGroupMode now has an official UI implementation
The groupedColumnMode
table option controls how grouped columns are displayed once a column has been grouped. There are three options:
"reorder"
(default) - Grouped columns will be displayed as the first columns in the table, followed by the 'mrt-row-expand' display column, followed by the remaining columns in their original order."remove"
- Grouped columns will be removed from the table and only their aggregate values will be displayed alongside the expand button in the 'mrt-row-expand' display column, followed by the remaining columns in their original order.false
- Grouping columns will have no effect on the column order. The 'mrt-row-expand' display column will be displayed as the first column in the table, followed by the remaining columns in their original order.
const table = useMaterialReactTable({columns,data,enableGrouping: true,groupedColumnMode: 'remove', //instead of default "reorder"});
State | Gender | First Name | Last Name | Age | Salary | |
---|---|---|---|---|---|---|
Utah (1) | ||||||
Male (5) | ||||||
Danika | Rodriguez | 57 | 31404 | |||
Alfonzo | Abernathy | 40 | 53374 | |||
Antwan | Zieme | 21 | 56638 | |||
Kathryn | Langworth | 39 | 25720 | |||
Haylee | Price | 57 | 59047 | |||
Alaska (2) | ||||||
Male (4) | ||||||
Eloisa | Kohler | 31 | 45801 | |||
Kian | Hand | 56 | 81062 | |||
Michale | Collier | 59 | 75197 | |||
Eldridge | Stroman | 42 | 59594 | |||
Female (4) | ||||||
Loyce | Schmidt | 29 | 76295 | |||
Alvera | Balistreri | 25 | 79844 | |||
Kayden | Emard | 35 | 98252 | |||
Domingo | Bauch | 36 | 35159 | |||
Arizona (1) | ||||||
Male (1) |
1import { useMemo, useState } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6} from 'material-react-table';7import { data, type Person } from './makeData';8import {9 FormControl,10 FormControlLabel,11 FormLabel,12 Radio,13 RadioGroup,14 Stack,15} from '@mui/material';1617const Example = () => {18 const columns = useMemo<MRT_ColumnDef<Person>[]>(19 //column definitions...48 );4950 //demo state51 const [groupedColumnMode, setGroupedColumnMode] = useState<52 false | 'remove' | 'reorder'53 >('reorder'); //default is 'reorder5455 const table = useMaterialReactTable({56 columns,57 data,58 enableGrouping: true,59 groupedColumnMode,60 initialState: {61 expanded: true, //expand all groups by default62 grouping: ['state', 'gender'], //an array of columns to group by by default (can be multiple)63 pagination: { pageIndex: 0, pageSize: 20 },64 },65 muiTableContainerProps: { sx: { maxHeight: '800px' } },66 });6768 return (69 <Stack gap="1rem">70 <DemoRadioGroup71 groupedColumnMode={groupedColumnMode}72 setGroupedColumnMode={setGroupedColumnMode}73 />74 <MaterialReactTable table={table} />75 </Stack>76 );77};7879export default Example;8081//demo...117
Disable Grouping Per Column
const columns = [{accessorKey: 'name',header: 'Name',enableGrouping: false, // disable grouping for this column},{accessorKey: 'age',header: 'Age',},];const table = useMaterialReactTable({columns,data,enableGrouping: true,});return <MaterialReactTable table={table} />;
Hide Drag Buttons for Grouping
If you do not want the drag buttons that come with the grouping feature, you can independently disable them without disabling the grouping feature entirely by setting the enableColumnDragging
table option to false
.
const table = useMaterialReactTable({columns,data,enableGrouping: true,enableColumnDragging: false, //do not show drag handle buttons, but still show grouping options in column actions menu});return <MaterialReactTable table={table} />;
Group Columns by Default
If you want columns to be grouped by default, you can set the grouping
state in either the initialState
or state
table option.
const table = useMaterialReactTable({columns,data,enableGrouping: true,initialState: { grouping: ['location', 'department'] }, //group by location and department by default});return <MaterialReactTable table={table} />;
Expand Grouped Rows by Default
In addition to grouping columns by default, you may also want those grouped rows to be expanded and visible by default, too. You can do this by setting the expanded
state to true
in either the initialState
or state
table option.
const table = useMaterialReactTable({columns,data,enableGrouping: true,initialState: {grouping: ['location', 'department'], //group by location and department by default and expand grouped rowsexpanded: true, //show grouped rows by default},});return <MaterialReactTable table={table} />;
Customize Expand Column
You can customize the expand column by using the displayColumnDefOptions
table option.
const table = useMaterialReactTable({columns,data,enableGrouping: true,displayColumnDefOptions: {'mrt-row-expand': {size: 120, //make the expand column wider},},});
Going further, you can completely overhaul how the expand column renders using custom Cell
and Header
renders here for advanced use cases.
const table = useMaterialReactTable({columns,data,enableGrouping: true,displayColumnDefOptions: {'mrt-row-expand': {Cell: ({ row, table }) => {return (<><MRT_ExpandButton row={row} table={table} />{/*custom content*/}</>);},Header: ({ table }) => {return (<><MRT_ExpandAllButton table={table} />{/*custom content*/}</>);},},},});
Groups | First Name | Last Name | Age | Salary | |
---|---|---|---|---|---|
Alabama(3) | |||||
Female(4) | |||||
Female | Thad | Wiegand | 64 | 56146 | |
Female | Reinhold | Reichel | 30 | 30531 | |
Female | Lurline | Koepp | 59 | 10645 | |
Female | Kody | Braun | 38 | 63733 | |
Male(2) | |||||
Male | Alivia | Ledner | 56 | 12591 | |
Male | Danyka | Gleason | 36 | 71238 | |
Nonbinary(1) | |||||
Nonbinary | Lionel | Hartmann | 30 | 58743 | |
Alaska(2) | |||||
Male(4) | |||||
Male | Eloisa | Kohler | 31 | 45801 | |
Male | Kian | Hand | 56 | 81062 | |
Male | Michale | Collier | 59 | 75197 | |
Male | Eldridge | Stroman | 42 | 59594 | |
Female(4) | |||||
Female | Loyce | Schmidt | 29 | 76295 | |
Female | Alvera | Balistreri | 25 | 79844 |
1import { useMemo, useState } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6 type MRT_Row,7 MRT_ExpandAllButton,8} from 'material-react-table';9import { data, type Person } from './makeData';10import { Box, Stack } from '@mui/material';1112const Example = () => {13 const columns = useMemo<MRT_ColumnDef<Person>[]>(14 //column definitions...43 );4445 const table = useMaterialReactTable({46 columns,47 data,48 displayColumnDefOptions: {49 'mrt-row-expand': {50 Header: () => (51 <Stack direction="row" alignItems="center">52 <MRT_ExpandAllButton table={table} />53 <Box>Groups</Box>54 </Stack>55 ),56 GroupedCell: ({ row, table }) => {57 const { grouping } = table.getState();58 return row.getValue(grouping[grouping.length - 1]);59 },60 enableResizing: true,61 muiTableBodyCellProps: ({ row }) => ({62 sx: (theme) => ({63 color:64 row.depth === 065 ? theme.palette.primary.main66 : row.depth === 167 ? theme.palette.secondary.main68 : undefined,69 }),70 }),71 size: 200,72 },73 },74 enableGrouping: true,75 enableColumnResizing: true,76 groupedColumnMode: 'remove',77 initialState: {78 density: 'compact',79 expanded: true, //expand all groups by default80 grouping: ['state', 'gender'], //an array of columns to group by by default (can be multiple)81 pagination: { pageIndex: 0, pageSize: 20 },82 sorting: [{ id: 'state', desc: false }],83 },84 });8586 return <MaterialReactTable table={table} />;87};8889export default Example;90
Manual Grouping
Manual Grouping means that the data
that you pass to the table is already grouped and aggregated, and you do not want Material React Table to do any of the grouping or aggregation for you. This is useful if you are using a backend API to do the grouping and aggregation for you, and you just want to display the results. However, you will need to put your data in the specific format that the expanding
features understand.
Learn more about Expanding Sub Rows and Aggregation Features in their own dedicated guides.