Row Selection Guide
Material React Table has a built-in row selection feature and makes it easy to manage the selection state yourself. This guide demonstrates how to enable row selection and customize the selection behavior.
Relevant Table Options
# | Prop Name | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
|
| MRT Row Selection Docs | ||
2 |
|
| MRT Row Selection Docs | ||
3 |
| MRT Row Selection Docs | |||
4 |
|
| |||
5 |
|
| |||
6 |
| TanStack Table Core Table Docs | |||
7 |
| Material UI Checkbox Props | |||
8 |
| Material UI Checkbox Props | |||
9 |
| TanStack Table Row Selection Docs | |||
10 |
|
| |||
11 |
|
| |||
12 |
|
| |||
Relevant State
# | State Option | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
|
| TanStack Table Row Selection Docs | ||
Enable Row Selection
Selection checkboxes can be enabled with the enableRowSelection
table option.
const table = useMaterialReactTable({columns,data,enableRowSelection: true,});return <MaterialReactTable table={table} />;
Enable Row Selection Conditionally Per Row
You can also enable row selection conditionally per row with the same enableRowSelection
table option, but with a callback function instead of a boolean.
const table = useMaterialReactTable({columns,data,enableRowSelection: (row) => row.original.age > 18, //disable row selection for rows with age <= 18});
Batch Row Selection
New in v2.11.0
By default, when the user holds down the Shift key and clicks a row, all rows between the last selected row and the clicked row will be selected. This can be disabled with the enableBatchRowSelection
table option.
const table = useMantineReactTable({columns,data,enableRowSelection: true,enableBatchRowSelection: false, //disable batch row selection with shift key});
Access Row Selection State
There are two ways to access the selection state. You can either manage the selection state yourself or read it from the table instance.
Manage Row Selection State
The row selection state is managed internally by default, but you will more than likely want to have access to that state yourself. Here is how you can simply get access to the row selection state, specifically:
const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({}); //ts type availableconst table = useMaterialReactTable({columns,data,enableRowSelection: true,onRowSelectionChange: setRowSelection,state: { rowSelection },});return <MaterialReactTable table={table} />;
Read Row Selection State from Table Instance
Alternatively, you can read the selection state directly from the table
instance like so:
const table = useMaterialReactTable({columns,data,enableRowSelection: true,renderTopToolbarCustomActions: ({ table }) => (<ButtononClick={() => {const rowSelection = table.getState().rowSelection; //read stateconst selectedRows = table.getSelectedRowModel().rows; //or read entire rows}}>Download Selected Users</Button>),});useEffect(() => {//fetch data based on row selection state or something}, [table.getState().rowSelection]);return <MaterialReactTable table={table} />;
Note:
table.getSelectedRowModel().rows
only really works with client-side pagination. UserowSelection
state if you are using server-side pagination. Row Models only contain rows based on thedata
you pass in.
Useful Row IDs
By default, the row.id
for each row in the table is simply the index of the row in the table. You can override this and instruct Material React Table to use a more useful Row ID with the getRowId
table option. For example, you may want something like this:
const table = useMaterialReactTable({columns,data,enableRowSelection: true,getRowId: (originalRow) => originalRow.userId,});
As rows get selected, the rowSelection
state will look like this:
{"3f25309c-8fa1-470f-811e-cdb082ab9017": true,"be731030-df83-419c-b3d6-9ef04e7f4a9f": true,...}
This can be very useful when you are trying to read your selection state and do something with your data as the row selection changes.
First Name | Last Name | Age | Address | City | State | |
---|---|---|---|---|---|---|
Dylan | Murray | 22 | 261 Erdman Ford | East Daphne | Kentucky | |
Raquel | Kohler | 18 | 769 Dominic Grove | Columbus | Ohio |
1import { useEffect, useMemo, useState } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6 type MRT_RowSelectionState,7} from 'material-react-table';89//data definitions...2021const data = [22 {23 userId: '3f25309c-8fa1-470f-811e-cdb082ab9017', //we'll use this as a unique row id24 firstName: 'Dylan',25 lastName: 'Murray',26 age: 22,27 address: '261 Erdman Ford',28 city: 'East Daphne',29 state: 'Kentucky',30 }, //data definitions...41];4243const Example = () => {44 const columns = useMemo<MRT_ColumnDef<Person>[]>(45 //column definitions...73 );7475 //optionally, you can manage the row selection state yourself76 const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});7778 const table = useMaterialReactTable({79 columns,80 data,81 enableRowSelection: true,82 getRowId: (row) => row.userId, //give each row a more useful id83 onRowSelectionChange: setRowSelection, //connect internal row selection state to your own84 state: { rowSelection }, //pass our managed row selection state to the table to use85 });8687 //do something when the row selection changes...88 useEffect(() => {89 console.info({ rowSelection }); //read your managed row selection state90 // console.info(table.getState().rowSelection); //alternate way to get the row selection state91 }, [rowSelection]);9293 return <MaterialReactTable table={table} />;94};9596export default Example;97
Select Row on Row Click
By default, a row can only be selected by either clicking the checkbox or radio button in the mrt-row-select
column. If you want to be able to select a row by clicking anywhere on the row, you can add your own onClick
function to a table body row like this:
const table = useMaterialReactTable({columns,data,enableRowSelection: true,//clicking anywhere on the row will select itmuiTableBodyRowProps: ({ row, staticRowIndex, table }) => ({onClick: (event) =>getMRT_RowSelectionHandler({ row, staticRowIndex, table })(event), //import this helper function from material-react-tablesx: { cursor: 'pointer' },}),});
Disable Select All
By default, if you enable selection for each row, there will also be a select all checkbox in the header of the checkbox column. It can be hidden with the enableSelectAll
table option.
const table = useMaterialReactTable({columns,data,enableRowSelection: true,enableSelectAll: false,});
Position or Hide Alert Banner Selection Message
By default, an alert banner will be show as rows are selected. You can use the positionToolbarAlertBanner
table option to show the alert banner in the top toolbar, bottom toolbar, as an overlay in the table head, or hide it completely.
const table = useMaterialReactTable({columns,data,enableRowSelection: true,positionToolbarAlertBanner: 'head-overlay', //show alert banner over table head, top toolbar, or bottom toolbar});
Single Row Selection
By default, the enableMultiRowSelection
table option is set to true
, which means that multiple rows can be selected at once with a checkbox. If you want to only allow a single row to be selected at a time, you can set this table option to false
and a radio button will be used instead of a checkbox.
const table = useMaterialReactTable({columns,data,enableMultiRowSelection: false, //shows radio buttons instead of checkboxesenableRowSelection: true,});
Select | First Name | Last Name | Age | Address | City | State |
---|---|---|---|---|---|---|
Dylan | Murray | 22 | 261 Erdman Ford | East Daphne | Kentucky | |
Raquel | Kohler | 18 | 769 Dominic Grove | Columbus | Ohio |
1import { useMemo, useState } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6 type MRT_RowSelectionState,7} from 'material-react-table';89//data definitions...2021const data = [22 //data definitions...42];4344const Example = () => {45 const columns = useMemo<MRT_ColumnDef<Person>[]>(46 //column definitions...74 );7576 //optionally, you can manage the row selection state yourself77 const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});7879 const table = useMaterialReactTable({80 columns,81 data,82 enableRowSelection: true,83 enableMultiRowSelection: false, //use radio buttons instead of checkboxes84 getRowId: (row) => row.userId, //give each row a more useful id85 muiTableBodyRowProps: ({ row }) => ({86 //add onClick to row to select upon clicking anywhere in the row87 onClick: row.getToggleSelectedHandler(),88 sx: { cursor: 'pointer' },89 }),90 positionToolbarAlertBanner: 'bottom', //move the alert banner to the bottom91 onRowSelectionChange: setRowSelection, //connect internal row selection state to your own92 state: { rowSelection }, //pass our managed row selection state to the table to use93 });9495 return <MaterialReactTable table={table} />;96};9798export default Example;99
Customize Select Checkboxes or Radio Buttons
The selection checkboxes can be customized with the muiSelectCheckboxProps
table option. Any prop that can be passed to a Mui Checkbox component can be specified here. For example, you may want to use a different color for the checkbox or use some logic to disable certain rows from being selected.
const table = useMaterialReactTable({columns,data,enableRowSelection: true,muiSelectCheckboxProps: {color: 'secondary',},});
Select | First Name | Last Name | Age | Address | City | State |
---|---|---|---|---|---|---|
Dylan | Murray | 22 | 261 Erdman Ford | East Daphne | Kentucky | |
Raquel | Kohler | 18 | 769 Dominic Grove | Columbus | Ohio | |
Ervin | Reinger | 20 | 566 Brakus Inlet | South Linda | West Virginia | |
Brittany | McCullough | 21 | 722 Emie Stream | Lincoln | Nebraska | |
Branson | Frami | 32 | 32188 Larkin Turnpike | Charleston | South Carolina |
1import { useMemo } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6} from 'material-react-table';7import { data, type Person } from './makeData';89const Example = () => {10 const columns = useMemo<MRT_ColumnDef<Person>[]>(11 //column definitions...40 );4142 const table = useMaterialReactTable({43 columns,44 data,45 enableSelectAll: false,46 enableRowSelection: (row) => row.original.age >= 21, //enable row selection conditionally per row47 muiSelectCheckboxProps: { color: 'secondary' },48 positionToolbarAlertBanner: 'head-overlay',49 });5051 return <MaterialReactTable table={table} />;52};5354export default Example;55
Manual Row Selection Without Checkboxes
You may have a use case where you want to be able to select rows by clicking them, but you do not want to show any checkboxes or radio buttons. You can do this by implementing a row selection feature yourself while keeping the enableRowSelection
table option false
so that the default selection behavior is disabled.
First Name | Last Name | Age | Address | City | State |
---|---|---|---|---|---|
Dylan | Murray | 22 | 261 Erdman Ford | East Daphne | Kentucky |
Raquel | Kohler | 18 | 769 Dominic Grove | Columbus | Ohio |
1import { useMemo, useState } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6 type MRT_RowSelectionState,7} from 'material-react-table';89//data definitions...2021const data = [22 //data definitions...42];4344const Example = () => {45 const columns = useMemo<MRT_ColumnDef<Person>[]>(46 //column definitions...75 );7677 const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});7879 const table = useMaterialReactTable({80 columns,81 data,82 getRowId: (row) => row.userId,83 muiTableBodyRowProps: ({ row }) => ({84 //implement row selection click events manually85 onClick: () =>86 setRowSelection((prev) => ({87 ...prev,88 [row.id]: !prev[row.id], //this is a simple toggle implementation89 })),90 selected: rowSelection[row.id],91 sx: {92 cursor: 'pointer',93 },94 }),95 onRowSelectionChange: setRowSelection,96 state: { rowSelection },97 });9899 return <MaterialReactTable table={table} />;100};101102export default Example;103
Sticky Pinned Row Selection
You can combine the row pinning feature with the row selection feature to create a cool user experience where selected rows always stay within view.
First Name | Last Name | Email | City | |
---|---|---|---|---|
Dylan | Murray | dmurray@yopmail.com | East Daphne | |
Raquel | Kohler | rkholer33@yopmail.com | Columbus | |
Ervin | Reinger | ereinger@mailinator.com | South Linda | |
Brittany | McCullough | bmccullough44@mailinator.com | Lincoln | |
Branson | Frami | bframi@yopmain.com | New York | |
Ben | Murray | benm@email.com | Salt Lake City | |
Elena | Smith | esmith@yopmail.com | Los Angeles | |
Michael | Johnson | mjohnson@mailinator.com | Chicago | |
Sophia | Brown | sbrown@yopmail.com | Houston | |
Lucas | Davis | ldavis@mailinator.com | Phoenix | |
Olivia | Garcia | ogarcia@yopmail.com | Philadelphia | |
Liam | Rodriguez | lrodriguez@mailinator.com | San Antonio | |
Emma | Martinez | emartinez@yopmail.com | San Diego | |
Noah | Hernandez | nhernandez@mailinator.com | Dallas | |
Ava | Lopez | alopez@yopmail.com | San Jose | |
William | Gonzalez | wgonzalez@mailinator.com | Austin | |
Isabella | Wilson | iwilson@yopmail.com | Jacksonville | |
James | Anderson | janderson@mailinator.com | Fort Worth | |
Mia | Thomas | mthomas@yopmail.com | Columbus | |
Alexander | Taylor | ataylor@mailinator.com | Charlotte | |
Grace | Moore | gmoore@yopmail.com | Indianapolis | |
Ethan | White | ewhite@mailinator.com | San Francisco | |
Lily | Harris | lharris@yopmail.com | Seattle | |
Daniel | Martin | dmartin@mailinator.com | Denver | |
Zoe | Jackson | zjackson@yopmail.com | Boston | |
Matthew | Thompson | mthompson@mailinator.com | Nashville | |
Ella | Garcia | egarcia@yopmail.com | Detroit | |
David | Martinez | dmartinez@mailinator.com | Portland | |
Aria | Robinson | arobinson@yopmail.com | Las Vegas | |
Joseph | Clark | jclark@mailinator.com | Baltimore |
1import { useMemo } from 'react';2import {3 MaterialReactTable,4 useMaterialReactTable,5 type MRT_ColumnDef,6} from 'material-react-table';7import { data, type Person } from './makeData';89const Example = () => {10 const columns = useMemo<MRT_ColumnDef<Person>[]>(11 //column definitions...32 );3334 const table = useMaterialReactTable({35 columns,36 data,37 enablePagination: false,38 enableRowPinning: true,39 enableRowSelection: true,40 enableStickyHeader: true,41 rowPinningDisplayMode: 'select-sticky',42 getRowId: (row) => row.email,43 initialState: {44 rowPinning: {45 top: ['ereinger@mailinator.com'],46 },47 rowSelection: {48 'ereinger@mailinator.com': true,49 },50 },51 muiTableContainerProps: {52 sx: {53 maxHeight: '400px',54 },55 },56 muiTableBodyRowProps: ({ row, table }) => {57 const { density } = table.getState();58 return {59 sx: {60 //Set a fixed height for pinned rows61 height: row.getIsPinned()62 ? `${63 //Default mrt row height estimates. Adjust as needed.64 density === 'compact' ? 37 : density === 'comfortable' ? 53 : 6965 }px`66 : undefined,67 },68 };69 },70 });7172 return <MaterialReactTable table={table} />;73};7475export default Example;76
View Extra Storybook Examples