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 Props
# | Prop Name 2 | 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
, then setting up an onDragEnd
event handler on the muiRowDragHandleProps
prop.
<MaterialReactTablecolumns={columns}data={data}enableRowOrderingenableSorting={false} //usually you do not want to sort when re-orderingmuiRowDragHandleProps={{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, { useMemo, useState } from 'react';2import {3 MaterialReactTable,4 type MRT_ColumnDef,5 type MRT_Row,6} from 'material-react-table';7import { data as initData, Person } from './makeData';89const Example = () => {10 const columns = useMemo<MRT_ColumnDef<Person>[]>(11 //column definitions...28 );2930 const [data, setData] = useState(() => initData);3132 return (33 <MaterialReactTable34 autoResetPageIndex={false}35 columns={columns}36 data={data}37 enableRowOrdering38 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 />53 );54};5556export default Example;57
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
prop to true
and setting up an onDragEnd
event handler on the muiRowDragHandleProps
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, { useMemo, useState } from 'react';2import {3 MaterialReactTable,4 type MRT_TableOptions,5 type MRT_ColumnDef,6 type MRT_Row,7} from 'material-react-table';8import { Box, Typography } from '@mui/material';9import { data, type Person } from './makeData';1011const Example = () => {12 const columns = useMemo<MRT_ColumnDef<Person>[]>(13 //column definitions...30 );3132 const [data1, setData1] = useState<Person[]>(() => data.slice(0, 3));33 const [data2, setData2] = useState<Person[]>(() => data.slice(3, 5));3435 const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);36 const [hoveredTable, setHoveredTable] = useState<string | null>(null);3738 const commonTableProps: Partial<MRT_TableOptions<Person>> & {39 columns: MRT_ColumnDef<Person>[];40 } = {41 columns,42 enableRowDragging: true,43 enableFullScreenToggle: false,44 muiTableContainerProps: {45 sx: {46 minHeight: '320px',47 },48 },49 onDraggingRowChange: setDraggingRow,50 state: { draggingRow },51 };5253 return (54 <Box55 sx={{56 display: 'grid',57 gridTemplateColumns: { xs: 'auto', lg: '1fr 1fr' },58 gap: '1rem',59 overflow: 'auto',60 p: '4px',61 }}62 >63 <MaterialReactTable64 {...commonTableProps}65 data={data1}66 getRowId={(originalRow) => `table-1-${originalRow.firstName}`}67 muiRowDragHandleProps={{68 onDragEnd: () => {69 if (hoveredTable === 'table-2') {70 setData2((data2) => [...data2, draggingRow!.original]);71 setData1((data1) =>72 data1.filter((d) => d !== draggingRow!.original),73 );74 }75 setHoveredTable(null);76 },77 }}78 muiTablePaperProps={{79 onDragEnter: () => setHoveredTable('table-1'),80 sx: {81 outline: hoveredTable === 'table-1' ? '2px dashed pink' : undefined,82 },83 }}84 renderTopToolbarCustomActions={() => (85 <Typography color="success.main" component="span" variant="h4">86 Nice List87 </Typography>88 )}89 />90 <MaterialReactTable91 {...commonTableProps}92 data={data2}93 defaultColumn={{94 size: 100,95 }}96 getRowId={(originalRow) => `table-2-${originalRow.firstName}`}97 muiRowDragHandleProps={{98 onDragEnd: () => {99 if (hoveredTable === 'table-1') {100 setData1((data1) => [...data1, draggingRow!.original]);101 setData2((data2) =>102 data2.filter((d) => d !== draggingRow!.original),103 );104 }105 setHoveredTable(null);106 },107 }}108 muiTablePaperProps={{109 onDragEnter: () => setHoveredTable('table-2'),110 sx: {111 outline: hoveredTable === 'table-2' ? '2px dashed pink' : undefined,112 },113 }}114 renderTopToolbarCustomActions={() => (115 <Typography color="error.main" component="span" variant="h4">116 Naughty List117 </Typography>118 )}119 />120 </Box>121 );122};123124export default Example;125
View Extra Storybook Examples