Row Ordering (DnD) Feature Guide
Material React Table has exposes all the APIs necessary to enable rich row drag and drop features that you can easily build to meet your needs. This includes the ability to reorder rows, drag rows to other tables, or drag rows to other UI in your application.
This is not the Sorting Guide which is a different feature.
Relevant Props
# | Prop Name | Type | Default Value | More Info Links | |
---|---|---|---|---|---|
1 |
| ||||
2 |
| Material UI IconButton Props | |||
3 |
| ||||
4 |
| ||||
Relevant State
Enable Row Ordering
A common use for row drag and drop is to allow users to reorder rows in a table. This can be done by setting the enableRowOrdering
prop to true
, and then setting up an onDragEnd
event handler on the muiTableBodyRowDragHandleProps
prop.
<MaterialReactTablecolumns={columns}data={data}enableRowOrderingenableSorting={false} //usually you do not want to sort when re-orderingmuiTableBodyRowDragHandleProps={{onDragEnd: (event, data) => {//data re-ordering logic here},}}/>
Move | First Name | Last Name | City |
---|---|---|---|
Dylan | Murray | East Daphne | |
Raquel | Kohler | Columbus | |
Ervin | Reinger | South Linda | |
Brittany | McCullough | Lincoln | |
Branson | Frami | Charleston |
1import React, { FC, useMemo, useState } from 'react';2import MaterialReactTable, {3 MRT_ColumnDef,4 MRT_Row,5} from 'material-react-table';6import { data as initData, Person } from './makeData';78const Example: FC = () => {9 const columns = useMemo<MRT_ColumnDef<Person>[]>(10 //column definitions...27 );2829 const [data, setData] = useState(() => initData);3031 return (32 <MaterialReactTable33 autoResetPageIndex={false}34 columns={columns}35 data={data}36 enableRowOrdering37 enableSorting={false}38 muiTableBodyRowDragHandleProps={({ table }) => ({39 onDragEnd: () => {40 const { draggingRow, hoveredRow } = table.getState();41 if (hoveredRow && draggingRow) {42 data.splice(43 (hoveredRow as MRT_Row<Person>).index,44 0,45 data.splice(draggingRow.index, 1)[0],46 );47 setData([...data]);48 }49 },50 })}51 />52 );53};5455export default Example;56
Drag and Drop Rows to Other UI or Tables
The Drag and Drop features are not limited to just internally within the same table. You can use them to drag rows to other UI in your application, or even to other tables. This can be done by setting the enableRowDragging
prop to true
, and then setting up an onDragEnd
event handler on the muiTableBodyRowDragHandleProps
prop to perform whatever logic you want to happen when a row is dropped.
Move | First Name | Last Name | City |
---|---|---|---|
Dylan | Murray | East Daphne | |
Raquel | Kohler | Columbus | |
Ervin | Reinger | South Linda |
Move | First Name | Last Name | City |
---|---|---|---|
Brittany | McCullough | Lincoln | |
Branson | Frami | Charleston |
1import React, { FC, useMemo, useState } from 'react';2import MaterialReactTable, {3 MaterialReactTableProps,4 MRT_ColumnDef,5 MRT_Row,6} from 'material-react-table';7import { Box, Typography } from '@mui/material';8import { data, Person } from './makeData';910const Example: FC = () => {11 const columns = useMemo<MRT_ColumnDef<Person>[]>(12 //column definitions...29 );3031 const [data1, setData1] = useState<Person[]>(() => data.slice(0, 3));32 const [data2, setData2] = useState<Person[]>(() => data.slice(3, 5));3334 const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);35 const [hoveredTable, setHoveredTable] = useState<string | null>(null);3637 const commonTableProps: Partial<MaterialReactTableProps<Person>> & {38 columns: MRT_ColumnDef<Person>[];39 } = {40 columns,41 enableRowDragging: true,42 enableFullScreenToggle: false,43 muiTableContainerProps: {44 sx: {45 minHeight: '320px',46 },47 },48 onDraggingRowChange: setDraggingRow,49 state: { draggingRow },50 };5152 return (53 <Box54 sx={{55 display: 'grid',56 gridTemplateColumns: { xs: 'auto', lg: '1fr 1fr' },57 gap: '1rem',58 overflow: 'auto',59 p: '4px',60 }}61 >62 <MaterialReactTable63 {...commonTableProps}64 data={data1}65 getRowId={(originalRow) => `table-1-${originalRow.firstName}`}66 muiTableBodyRowDragHandleProps={{67 onDragEnd: () => {68 if (hoveredTable === 'table-2') {69 setData2((data2) => [...data2, draggingRow!.original]);70 setData1((data1) =>71 data1.filter((d) => d !== draggingRow!.original),72 );73 }74 setHoveredTable(null);75 },76 }}77 muiTablePaperProps={{78 onDragEnter: () => setHoveredTable('table-1'),79 sx: {80 outline: hoveredTable === 'table-1' ? '2px dashed pink' : undefined,81 },82 }}83 renderTopToolbarCustomActions={() => (84 <Typography color="success.main" component="span" variant="h4">85 Nice List86 </Typography>87 )}88 />89 <MaterialReactTable90 {...commonTableProps}91 data={data2}92 defaultColumn={{93 size: 100,94 }}95 getRowId={(originalRow) => `table-2-${originalRow.firstName}`}96 muiTableBodyRowDragHandleProps={{97 onDragEnd: () => {98 if (hoveredTable === 'table-1') {99 setData1((data1) => [...data1, draggingRow!.original]);100 setData2((data2) =>101 data2.filter((d) => d !== draggingRow!.original),102 );103 }104 setHoveredTable(null);105 },106 }}107 muiTablePaperProps={{108 onDragEnter: () => setHoveredTable('table-2'),109 sx: {110 outline: hoveredTable === 'table-2' ? '2px dashed pink' : undefined,111 },112 }}113 renderTopToolbarCustomActions={() => (114 <Typography color="error.main" component="span" variant="h4">115 Naughty List116 </Typography>117 )}118 />119 </Box>120 );121};122123export default Example;124
View Extra Storybook Examples