Examples › Row dragging
Starting with v7.11.3
, Mantine DataTable also supports row dragging (implemented with @hello-pangea/dnd library in this PR).
Here is how you would implement it in your project:
'use client';
import { DragDropContext, Draggable, type DropResult, Droppable } from '@hello-pangea/dnd';
import { TableTd } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { IconGripVertical } from '@tabler/icons-react';
import { DataTable, DataTableColumn, DataTableDraggableRow } from 'mantine-datatable';
import { useState } from 'react';
import companies from '~/data/companies.json';
interface RecordData {
id: string;
name: string;
streetAddress: string;
city: string;
state: string;
missionStatement: string;
}
export function RowDraggingExample() {
const [records, setRecords] = useState<RecordData[]>(companies);
const handleDragEnd = (result: DropResult) => {
if (!result.destination) return;
const items = Array.from(records);
const sourceIndex = result.source.index;
const destinationIndex = result.destination.index;
const [reorderedItem] = items.splice(sourceIndex, 1);
items.splice(destinationIndex, 0, reorderedItem);
setRecords(items);
notifications.show({
title: 'Table reordered',
message: `The company named "${items[sourceIndex].name}" has been moved from position ${sourceIndex + 1} to ${destinationIndex + 1}.`,
color: 'blue',
});
};
const columns: DataTableColumn<RecordData>[] = [
// add empty header column for the drag handle
{ accessor: '', hiddenContent: true, width: 30 },
{ accessor: 'name', width: 150 },
{ accessor: 'streetAddress', width: 150 },
{ accessor: 'city', width: 150 },
{ accessor: 'state', width: 150 },
];
return (
<DragDropContext onDragEnd={handleDragEnd}>
<DataTable<RecordData>
columns={columns}
records={records}
height={400}
withTableBorder
withColumnBorders
tableWrapper={({ children }) => (
<Droppable droppableId="datatable">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{children}
{provided.placeholder}
</div>
)}
</Droppable>
)}
styles={{ table: { tableLayout: 'fixed' } }}
rowFactory={({ record, index, rowProps, children }) => (
<Draggable key={record.id} draggableId={record.id} index={index}>
{(provided, snapshot) => (
<DataTableDraggableRow isDragging={snapshot.isDragging} {...rowProps} {...provided.draggableProps}>
{/** custom drag handle */}
<TableTd {...provided.dragHandleProps} ref={provided.innerRef}>
<IconGripVertical size={16} />
</TableTd>
{children}
</DataTableDraggableRow>
)}
</Draggable>
)}
/>
</DragDropContext>
);
}
The code above will produce the following result:
Name | Street address | City | State | |
---|---|---|---|---|
Feest, Bogan and Herzog | 21716 Ratke Drive | Stromanport | WY | |
Cummerata - Kuhlman | 6389 Dicki Stream | South Gate | NH | |
Goyette Inc | 8873 Mertz Rapid | Dorthyside | ID | |
Runte Inc | 2996 Ronny Mount | McAllen | MA | |
Goldner, Rohan and Lehner | 632 Broadway Avenue | North Louie | WY | |
Doyle, Hodkiewicz and O'Connell | 576 Joyce Ways | Tyraburgh | KS | |
Rau - O'Hara | 7508 Lansdowne Road | Shieldsborough | MI | |
Tillman - Jacobi | 57918 Gwendolyn Circles | Sheridanport | MI | |
Connelly, Feest and Hodkiewicz | 7057 Stanley Road | Kearaburgh | CA | |
Shanahan, Robel and Beier | 378 Berta Crescent | West Gerry | KS | |
Kling - McLaughlin | 8346 Kertzmann Square | South Joesph | ID | |
Jogi - McLaughlin | 83462 Shazam Street | North Joesph | ID | |
Jogi - McLaughlin | 83462 Shazam Street | North Joesph | ID |
No records