Editing Feature Guide
If your tables need full CRUD functionality, you can enable editing features in Material React Table.
There are 4 visually distinct editing modes to choose from, whether you want to let users edit data in a modal, inline 1 row at a time, 1 cell at a time, or just always have editing enabled for every cell.
Relevant Props
# | Prop Name | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
|
| MRT Editing Docs | ||
2 |
| MRT Editing Docs | |||
3 |
| Material UI TextField Props | |||
4 |
| ||||
5 |
| MRT Editing Docs | |||
6 |
| ||||
7 |
| MRT Editing Docs | |||
Relevant Column Options
# | Column Option | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| ||||
2 |
| Material UI TextField API | |||
Relevant State Options
Enable Editing
To enable editing, first you just need to set the enableEditing
prop to true
.
<MaterialTable columns={columns} data={data} enableEditing={true} />
However, this is just the start. You will need to hook up logic and event listeners, but it depends on which editing mode you want to use.
Editing Modes
Material React Table has 4 supported editing modes: "modal"
(default), "row"
, "cell"
and "table"
. You can specify which editing mode you want to use by passing the editingMode
prop.
Modal Editing Mode
The "modal"
editing mode opens up a dialog where the user can edit data for 1 row at a time. No data is saved to the table until the user clicks the save button. Clicking the cancel button clears out any changes that were made on that row.
An onEditingRowSave
callback function prop must be provided where you will get access to the updated row data so that changes can be processed and saved. It is up to you how you handle the data. This function has a exitEditingMode
parameter that must be called in order to exit editing mode upon save. The reason for this is so that you can perform validation checks before letting the modal close.
The
onEditingRowSave
callback function prop includes anexitEditingMode
parameter that must be called in order to exit editing mode upon save. The reason for this is so that you can perform validation checks before letting the modal close.
Actions | First Name | Last Name | Address | City | State |
---|---|---|---|---|---|
Dylan | Murray | 261 Erdman Ford | East Daphne | Kentucky | |
Raquel | Kohler | 769 Dominic Grove | Columbus | Ohio | |
Ervin | Reinger | 566 Brakus Inlet | South Linda | West Virginia | |
Brittany | McCullough | 722 Emie Stream | Lincoln | Nebraska | |
Branson | Frami | 32188 Larkin Turnpike | Charleston | South Carolina |
1import React, { FC, useMemo, useState } from 'react';2import MaterialReactTable, {3 MaterialReactTableProps,4 MRT_ColumnDef,5} from 'material-react-table';6import { data, Person } from './makeData';78const Example: FC = () => {9 const columns = useMemo<MRT_ColumnDef<Person>[]>(10 () => [11 //column definitions...34 ],35 [],36 );3738 const [tableData, setTableData] = useState<Person[]>(() => data);3940 const handleSaveRow: MaterialReactTableProps<Person>['onEditingRowSave'] =41 async ({ exitEditingMode, row, values }) => {42 //if using flat data and simple accessorKeys/ids, you can just do a simple assignment here.43 tableData[row.index] = values;44 //send/receive api updates here45 setTableData([...tableData]);46 exitEditingMode(); //required to exit editing mode47 };4849 return (50 <MaterialReactTable51 columns={columns}52 data={tableData}53 editingMode="modal" //default54 enableEditing55 onEditingRowSave={handleSaveRow}56 />57 );58};5960export default Example;61
Row Editing Mode
The row
editing mode is an inline row editing mode. When edit mode is activated, the row shows the edit components in the data cells. No data is saved to the table until the user clicks the save button. Clicking the cancel button clears out any changes that were made on that row.
You must provide an onEditingRowSave
callback function prop where you will get access to the updated row data so that changes can be processed and saved. It is up to you how you handle the data. This function has a exitEditingMode
parameter that must be called in order to exit editing mode upon save. The reason for this is so that you can perform validation checks before letting the modal close.
The
onEditingRowSave
callback function prop includes anexitEditingMode
parameter that must be called in order to exit editing mode upon save. The reason for this is so that you can perform validation checks before letting the modal close.
Actions | First Name | Last Name | Address | City | State |
---|---|---|---|---|---|
Dylan | Murray | 261 Erdman Ford | East Daphne | Kentucky | |
Raquel | Kohler | 769 Dominic Grove | Columbus | Ohio | |
Ervin | Reinger | 566 Brakus Inlet | South Linda | West Virginia | |
Brittany | McCullough | 722 Emie Stream | Lincoln | Nebraska | |
Branson | Frami | 32188 Larkin Turnpike | Charleston | South Carolina |
1import React, { FC, useMemo, useState } from 'react';2import MaterialReactTable, {3 MaterialReactTableProps,4 MRT_ColumnDef,5} from 'material-react-table';6import { data, Person } from './makeData';78const Example: FC = () => {9 const columns = useMemo<MRT_ColumnDef<Person>[]>(10 () => [11 //column definitions...34 ],35 [],36 );3738 const [tableData, setTableData] = useState<Person[]>(() => data);3940 const handleSaveRow: MaterialReactTableProps<Person>['onEditingRowSave'] =41 async ({ exitEditingMode, row, values }) => {42 //if using flat data and simple accessorKeys/ids, you can just do a simple assignment here.43 tableData[row.index] = values;44 //send/receive api updates here45 setTableData([...tableData]);46 exitEditingMode(); //required to exit editing mode47 };4849 return (50 <MaterialReactTable51 columns={columns}52 data={tableData}53 editingMode="row"54 enableEditing55 onEditingRowSave={handleSaveRow}56 />57 );58};5960export default Example;61
Cell Editing Mode
The cell
editing mode is a bit simpler visually. Uses double-click cells to activate editing mode, but only for that cell.
Then there is a bit of work for you to do to wire up either the onBlur
, onChange
, etc. events yourself in order to save the table data. This can be done in the muiTableBodyCellEditTextFieldProps
prop or column definition option.
First Name | Last Name | Address | City | State |
---|---|---|---|---|
Dylan | Murray | 261 Erdman Ford | East Daphne | Kentucky |
Raquel | Kohler | 769 Dominic Grove | Columbus | Ohio |
Ervin | Reinger | 566 Brakus Inlet | South Linda | West Virginia |
Brittany | McCullough | 722 Emie Stream | Lincoln | Nebraska |
Branson | Frami | 32188 Larkin Turnpike | Charleston | South Carolina |
1import React, { FC, useMemo, useState } from 'react';2import MaterialReactTable, {3 MRT_Cell,4 MRT_ColumnDef,5} from 'material-react-table';6import { Typography } from '@mui/material';7import { data, Person } from './makeData';89const Example: FC = () => {10 const columns = useMemo<MRT_ColumnDef<Person>[]>(11 () => [12 //column definitions...34 ],35 [],36 );3738 const [tableData, setTableData] = useState<Person[]>(() => data);3940 const handleSaveCell = (cell: MRT_Cell<Person>, value: any) => {41 //if using flat data and simple accessorKeys/ids, you can just do a simple assignment here42 tableData[cell.row.index][cell.column.id as keyof Person] = value;43 //send/receive api updates here44 setTableData([...tableData]); //re-render with new data45 };4647 return (48 <MaterialReactTable49 columns={columns}50 data={tableData}51 editingMode="cell"52 enableEditing53 muiTableBodyCellEditTextFieldProps={({ cell }) => ({54 //onBlur is more efficient, but could use onChange instead55 onBlur: (event) => {56 handleSaveCell(cell, event.target.value);57 },58 })}59 renderBottomToolbarCustomActions={() => (60 <Typography sx={{ fontStyle: 'italic', p: '0 1rem' }} variant="body2">61 Double-Click a Cell to Edit62 </Typography>63 )}64 />65 );66};6768export default Example;69
Table Editing Mode
The table
editing mode is similar to the cell
editing mode, but it simply has all of the data cells in the table become editable all at once.
To save data, you must hook up either the onBlur
, onChange
, etc. events yourself. This can be done in the muiTableBodyCellEditTextFieldProps
prop or column definition option.
First Name | Last Name | Address | City | State |
---|---|---|---|---|
1import React, { FC, useMemo, useState } from 'react';2import MaterialReactTable, {3 MRT_Cell,4 MRT_ColumnDef,5} from 'material-react-table';6import { data, Person } from './makeData';78const Example: FC = () => {9 const columns = useMemo<MRT_ColumnDef<Person>[]>(10 () => [11 //column definitions...33 ],34 [],35 );3637 const [tableData, setTableData] = useState<Person[]>(() => data);3839 const handleSaveCell = (cell: MRT_Cell<Person>, value: any) => {40 //if using flat data and simple accessorKeys/ids, you can just do a simple assignment here41 tableData[cell.row.index][cell.column.id as keyof Person] = value;42 //send/receive api updates here43 setTableData([...tableData]); //re-render with new data44 };4546 return (47 <MaterialReactTable48 columns={columns}49 data={tableData}50 editingMode="table"51 enableEditing52 muiTableBodyCellEditTextFieldProps={({ cell }) => ({53 //onBlur is more efficient, but could use onChange instead54 onBlur: (event) => {55 handleSaveCell(cell, event.target.value);56 },57 variant: 'outlined',58 })}59 />60 );61};6263export default Example;64
Customizing Editing Components
You can pass any MUI TextField Props with the muiTableBodyCellEditTextFieldProps
prop.
const columns = [{accessor: 'age',header: 'Age',muiTableBodyCellEditTextFieldProps: {required: true,type: 'number',variant: 'outlined',},},];
Add Validation to Editing Components
You can add validation to the editing components by using the muiTableBodyCellEditTextFieldProps
events. You can write your validation logic and hook it up to either the onBlur
, onChange
, etc. events, then set the error
and helperText
props accordingly.
If you are implementing validation, you may also need to use the onEditingRowCancel
prop to clear the validation error state.
const [validationErrors, setValidationErrors] = useState({});const columns = [{accessor: 'age',header: 'Age',muiTableBodyCellEditTextFieldProps: {error: !!validationErrors.age, //highlight mui text field red error colorhelperText: validationErrors.age, //show error message in helper text.required: true,type: 'number',onChange: (event) => {const value = event.target.value;//validation logicif (!value) {setValidationErrors((prev) => ({ ...prev, age: 'Age is required' }));} else if (value < 18) {setValidationErrors({...validationErrors,age: 'Age must be 18 or older',});} else {delete validationErrors.age;setValidationErrors({ ...validationErrors });}},},},];
Use Custom Editing Components
If you need to use a much more complicated Editing component than the built-in textfield, you can specify a custom editing component with the Edit
column definition option.
const columns = [{accessorKey: 'email',header: 'Email',Edit: ({ cell, column, table }) => <Autocomplete />,},];
Customize Actions/Edit Column
You can customize the actions column in a few different ways in the displayColumnDefOptions
prop's 'mrt-row-actions'
section.
<MaterialReactTabledata={data}columns={columns}displayColumnDefOptions={{'mrt-row-actions': {header: 'Edit', //change "Actions" to "Edit"//use a text button instead of a icon buttonCell: ({ row, table }) => (<Button onClick={() => table.setEditingRow(row)}>Edit Customer</Button>),},}}/>
React-Hook-Form Example
TODO