Row Ordering (DnD) Feature Guide
Material React Table has exposed 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 Table Options
# | 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
table option to true
, then setting up an onDragEnd
event handler on the muiRowDragHandleProps
table option.
const table = useMaterialReactTable({columns,data,enableRowOrdering: true,enableSorting: false, //usually you do not want to sort when re-orderingmuiRowDragHandleProps: {onDragEnd: (event, data) => {//data re-ordering logic here},},});return <MaterialReactTable table={table} />;
Move | First Name | Last Name | City |
---|---|---|---|
Dylan | Murray | East Daphne | |
Raquel | Kohler | Columbus | |
Ervin | Reinger | South Linda | |
Brittany | McCullough | Lincoln | |
Branson | Frami | Charleston |
1import { useMemo, useState } from 'react';2import {3 useMaterialReactTable,4 type MRT_ColumnDef,5 type MRT_Row,6 MRT_TableContainer,7} from 'material-react-table';8import { data as initData, type Person } from './makeData';910const Example = () => {11 const columns = useMemo<MRT_ColumnDef<Person>[]>(12 //column definitions...29 );3031 const [data, setData] = useState(() => initData);3233 const table = useMaterialReactTable({34 autoResetPageIndex: false,35 columns,36 data,37 enableRowOrdering: true,38 enableSorting: false,39 muiRowDragHandleProps: ({ table }) => ({40 onDragEnd: () => {41 const { draggingRow, hoveredRow } = table.getState();42 if (hoveredRow && draggingRow) {43 data.splice(44 (hoveredRow as MRT_Row<Person>).index,45 0,46 data.splice(draggingRow.index, 1)[0],47 );48 setData([...data]);49 }50 },51 }),52 });5354 return <MRT_TableContainer table={table} />;55};5657export default Example;58
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 also use them to drag rows to other UI elements in your application or even to other tables. This can be done by setting the enableRowDragging
table option to true
and setting up an onDragEnd
event handler on the muiRowDragHandleProps
table option 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 { useMemo, useState } from 'react';2import {3 type MRT_TableOptions,4 type MRT_ColumnDef,5 type MRT_Row,6 MaterialReactTable,7 useMaterialReactTable,8} from 'material-react-table';9import { Box, Typography } from '@mui/material';10import { data, type Person } from './makeData';1112const Example = () => {13 const columns = useMemo<MRT_ColumnDef<Person>[]>(14 //column definitions...31 );3233 const [data1, setData1] = useState<Person[]>(() => data.slice(0, 3));34 const [data2, setData2] = useState<Person[]>(() => data.slice(3, 5));3536 const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);37 const [hoveredTable, setHoveredTable] = useState<string | null>(null);3839 const commonTableProps: Partial<MRT_TableOptions<Person>> & {40 columns: MRT_ColumnDef<Person>[];41 } = {42 columns,43 enableRowDragging: true,44 enableFullScreenToggle: false,45 muiTableContainerProps: {46 sx: {47 minHeight: '320px',48 },49 },50 onDraggingRowChange: setDraggingRow,51 state: { draggingRow },52 };5354 const table1 = useMaterialReactTable({55 ...commonTableProps,56 data: data1,57 getRowId: (originalRow) => `table-1-${originalRow.firstName}`,58 muiRowDragHandleProps: {59 onDragEnd: () => {60 if (hoveredTable === 'table-2') {61 setData2((data2) => [...data2, draggingRow!.original]);62 setData1((data1) => data1.filter((d) => d !== draggingRow!.original));63 }64 setHoveredTable(null);65 },66 },67 muiTablePaperProps: {68 onDragEnter: () => setHoveredTable('table-1'),69 sx: {70 outline: hoveredTable === 'table-1' ? '2px dashed pink' : undefined,71 },72 },73 renderTopToolbarCustomActions: () => (74 <Typography color="success.main" component="span" variant="h4">75 Nice List76 </Typography>77 ),78 });7980 const table2 = useMaterialReactTable({81 ...commonTableProps,82 data: data2,83 defaultColumn: {84 size: 100,85 },86 getRowId: (originalRow) => `table-2-${originalRow.firstName}`,87 muiRowDragHandleProps: {88 onDragEnd: () => {89 if (hoveredTable === 'table-1') {90 setData1((data1) => [...data1, draggingRow!.original]);91 setData2((data2) => data2.filter((d) => d !== draggingRow!.original));92 }93 setHoveredTable(null);94 },95 },96 muiTablePaperProps: {97 onDragEnter: () => setHoveredTable('table-2'),98 sx: {99 outline: hoveredTable === 'table-2' ? '2px dashed pink' : undefined,100 },101 },102 renderTopToolbarCustomActions: () => (103 <Typography color="error.main" component="span" variant="h4">104 Naughty List105 </Typography>106 ),107 });108109 return (110 <Box111 sx={{112 display: 'grid',113 gridTemplateColumns: { xs: 'auto', lg: '1fr 1fr' },114 gap: '1rem',115 overflow: 'auto',116 p: '4px',117 }}118 >119 <MaterialReactTable table={table1} />120 <MaterialReactTable table={table2} />121 </Box>122 );123};124125export default Example;126
View Extra Storybook Examples