Examples › Column dragging and toggling
Starting with v7.3
, Mantine DataTable supports column toggling and drag-and-drop reordering, thanks to the outstanding work of Giovambattista Fazioli.
Column drag-and-drop reordering
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
In order to enable column dragging you’ll have to:
- add a
storeColumnsKey: 'your_key'
property to the DataTable (since the order of the columns is persisted in the local storage); - add a
draggable: true
property to each dragging candidate column; - use the
useDataTableColumns()
hook to get the sorted columns.
'use client';
import { Button, Group, Stack } from '@mantine/core';
import { DataTable, useDataTableColumns } from 'mantine-datatable';
import { companies, type Company } from '~/data';
export default function DraggingExample() {
const key = 'draggable-example';
const { effectiveColumns, resetColumnsOrder } = useDataTableColumns<Company>({
key,
columns: [
{ accessor: 'name', width: '40%', draggable: true },
{ accessor: 'streetAddress', width: '60%', draggable: true },
{ accessor: 'city', width: 160, draggable: true },
{ accessor: 'state', textAlign: 'right' },
],
});
return (
<Stack>
<DataTable
withTableBorder
withColumnBorders
storeColumnsKey={key}
records={companies}
columns={effectiveColumns}
/>
<Group justify="right">
<Button onClick={resetColumnsOrder}>Reset Column Order</Button>
</Group>
</Stack>
);
}
The default order of the columns is the order in which they are defined in the
columns
prop.Column toggling
In the example below:
- you can toggle the first 3 columns;
- the last column is not toggleable and will always be visible;
- the first column is toggled off by default.
Right-click on the header to select the columns you want to toggle.
Street Address | City | |
---|---|---|
21716 Ratke Drive | Stromanport | WY |
6389 Dicki Stream | South Gate | NH |
8873 Mertz Rapid | Dorthyside | ID |
2996 Ronny Mount | McAllen | MA |
632 Broadway Avenue | North Louie | WY |
576 Joyce Ways | Tyraburgh | KS |
7508 Lansdowne Road | Shieldsborough | MI |
57918 Gwendolyn Circles | Sheridanport | MI |
7057 Stanley Road | Kearaburgh | CA |
378 Berta Crescent | West Gerry | KS |
8346 Kertzmann Square | South Joesph | ID |
83462 Shazam Street | North Joesph | ID |
83462 Shazam Street | North Joesph | ID |
No records
In order to enable column toggling you’ll have to:
- add a
storeColumnsKey: 'your_key'
property to the DataTable (since the order of the columns is persisted in the local storage); - add a
toggleable: true
property to each toggling candidate column; - use the
useDataTableColumns()
hook to get the sorted columns.
'use client';
import { Button, Group, Stack, Text } from '@mantine/core';
import { IconBuildingCommunity, IconBuildingSkyscraper, IconMap, IconRoadSign } from '@tabler/icons-react';
import { DataTable, useDataTableColumns } from 'mantine-datatable';
import { companies } from '~/data';
export default function TogglingExample() {
const key = 'toggleable-example';
const { effectiveColumns, resetColumnsToggle } = useDataTableColumns({
key,
columns: [
{
accessor: 'name',
title: (
<Group gap={4} mt={-1}>
<IconBuildingSkyscraper size={16} />
<Text inherit mt={1}>
Company
</Text>
</Group>
),
width: '40%',
toggleable: true,
defaultToggle: false,
},
{
accessor: 'streetAddress',
title: (
<Group gap={4} mt={-1}>
<IconRoadSign size={16} />
<Text inherit mt={1}>
Street Address
</Text>
</Group>
),
width: '60%',
toggleable: true,
},
{
accessor: 'city',
title: (
<Group gap={4} mt={-1}>
<IconBuildingCommunity size={16} />
<Text inherit mt={1}>
City
</Text>
</Group>
),
width: 160,
toggleable: true,
},
{
accessor: 'state',
textAlign: 'right',
title: (
<Group justify="right">
<IconMap size={16} />
</Group>
),
},
],
});
return (
<Stack>
<DataTable
withTableBorder
withColumnBorders
storeColumnsKey={key}
records={companies}
columns={effectiveColumns}
/>
<Group justify="right">
<Button onClick={resetColumnsToggle}>Reset toggled columns</Button>
</Group>
</Stack>
);
}
You may define which columns will be toggled by default by setting the
defaultToggle
property to false
.Add & Remove column at run-time
Of course, you may need to add or remove columns at run-time. In this case, you can directly modify the array of columns without needing to perform any operations.
Street Address | City | |
---|---|---|
21716 Ratke Drive | Stromanport | WY |
6389 Dicki Stream | South Gate | NH |
8873 Mertz Rapid | Dorthyside | ID |
2996 Ronny Mount | McAllen | MA |
632 Broadway Avenue | North Louie | WY |
576 Joyce Ways | Tyraburgh | KS |
7508 Lansdowne Road | Shieldsborough | MI |
57918 Gwendolyn Circles | Sheridanport | MI |
7057 Stanley Road | Kearaburgh | CA |
378 Berta Crescent | West Gerry | KS |
8346 Kertzmann Square | South Joesph | ID |
83462 Shazam Street | North Joesph | ID |
83462 Shazam Street | North Joesph | ID |
No records
'use client';
import { Button, Group, Stack, Text } from '@mantine/core';
import { IconBuildingCommunity, IconBuildingSkyscraper, IconMap, IconRoadSign } from '@tabler/icons-react';
import { DataTable, DataTableColumn, useDataTableColumns } from 'mantine-datatable';
import { useState } from 'react';
import { companies } from '~/data';
export default function DynamicColumnExample() {
const key = 'dynamic-column-example';
const [columns, setColumns] = useState<DataTableColumn[]>([
{
accessor: 'name',
title: (
<Group gap={4} mt={-1}>
<IconBuildingSkyscraper size={16} />
<Text inherit mt={1}>
Company
</Text>
</Group>
),
width: '40%',
toggleable: true,
defaultToggle: false,
},
{
accessor: 'streetAddress',
title: (
<Group gap={4} mt={-1}>
<IconRoadSign size={16} />
<Text inherit mt={1}>
Street Address
</Text>
</Group>
),
width: '60%',
toggleable: true,
},
{
accessor: 'city',
title: (
<Group gap={4} mt={-1}>
<IconBuildingCommunity size={16} />
<Text inherit mt={1}>
City
</Text>
</Group>
),
width: 160,
toggleable: true,
},
{
accessor: 'state',
textAlign: 'right',
title: (
<Group justify="right">
<IconMap size={16} />
</Group>
),
},
]);
const { effectiveColumns, resetColumnsToggle } = useDataTableColumns({
key,
columns,
});
// add or remove the whole record with missionStatement accessor
function toggleColumnMissionStatement() {
const newColumns = columns.filter((col) => col.accessor !== 'missionStatement');
if (columns.length === newColumns.length) {
newColumns.push({
accessor: 'missionStatement',
title: (
<Group gap={4} mt={-1} wrap="nowrap">
<IconBuildingSkyscraper size={16} />
<Text inherit mt={1}>
Mission Statement
</Text>
</Group>
),
width: '40%',
toggleable: true,
defaultToggle: true,
});
}
setColumns(newColumns);
}
return (
<Stack>
<Group>
<Button onClick={toggleColumnMissionStatement}>Toggle Mission Statement column</Button>
</Group>
<DataTable
withTableBorder
withColumnBorders
storeColumnsKey={key}
records={companies}
columns={effectiveColumns}
/>
<Group justify="right">
<Button onClick={resetColumnsToggle}>Reset toggled columns</Button>
</Group>
</Stack>
);
}
Dragging and toggling with context menu reset
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
'use client';
import { IconColumnRemove, IconColumns3 } from '@tabler/icons-react';
import { DataTable, useDataTableColumns } from 'mantine-datatable';
import { useContextMenu } from 'mantine-contextmenu';
import { companies } from '~/data';
export default function DraggingTogglingResetExample() {
const { showContextMenu } = useContextMenu();
const key = 'toggleable-reset-example';
const { effectiveColumns, resetColumnsOrder, resetColumnsToggle } = useDataTableColumns({
key,
columns: [
{ accessor: 'name', width: '40%', toggleable: true, draggable: true },
{ accessor: 'streetAddress', width: '60%', toggleable: true, draggable: true },
{ accessor: 'city', width: 160, toggleable: true, draggable: true },
{ accessor: 'state', textAlign: 'right' },
],
});
return (
<DataTable
withTableBorder
withColumnBorders
storeColumnsKey={key}
records={companies}
columns={effectiveColumns}
onRowContextMenu={({ event }) =>
showContextMenu([
{
key: 'reset-toggled-columns',
icon: <IconColumnRemove size={16} />,
onClick: resetColumnsToggle,
},
{
key: 'reset-columns-order',
icon: <IconColumns3 size={16} />,
onClick: resetColumnsOrder,
},
])(event)
}
/>
);
}
Complex usage
Name | Street address | City | State |
---|---|---|---|
Connelly, Feest and Hodkiewicz | 7057 Stanley Road | Kearaburgh | CA |
Cummerata - Kuhlman | 6389 Dicki Stream | South Gate | NH |
Doyle, Hodkiewicz and O'Connell | 576 Joyce Ways | Tyraburgh | KS |
Feest, Bogan and Herzog | 21716 Ratke Drive | Stromanport | WY |
Goldner, Rohan and Lehner | 632 Broadway Avenue | North Louie | WY |
Goyette Inc | 8873 Mertz Rapid | Dorthyside | ID |
Jogi - McLaughlin | 83462 Shazam Street | North Joesph | ID |
Jogi - McLaughlin | 83462 Shazam Street | North Joesph | ID |
Kling - McLaughlin | 8346 Kertzmann Square | South Joesph | ID |
Rau - O'Hara | 7508 Lansdowne Road | Shieldsborough | MI |
Runte Inc | 2996 Ronny Mount | McAllen | MA |
Shanahan, Robel and Beier | 378 Berta Crescent | West Gerry | KS |
Tillman - Jacobi | 57918 Gwendolyn Circles | Sheridanport | MI |
No records
'use client';
import { IconColumnRemove, IconColumns3 } from '@tabler/icons-react';
import { DataTable, useDataTableColumns, type DataTableSortStatus } from 'mantine-datatable';
import sortBy from 'lodash/sortBy';
import { useContextMenu } from 'mantine-contextmenu';
import { useEffect, useState } from 'react';
import { companies, type Company } from '~/data';
export default function DraggingTogglingComplexExample() {
const { showContextMenu } = useContextMenu();
const [sortStatus, setSortStatus] = useState<DataTableSortStatus<Company>>({
columnAccessor: 'name',
direction: 'asc',
});
const [records, setRecords] = useState(sortBy(companies, 'name'));
useEffect(() => {
const data = sortBy(companies, sortStatus.columnAccessor) as Company[];
setRecords(sortStatus.direction === 'desc' ? data.reverse() : data);
}, [sortStatus]);
const key = 'toggleable-reset-example';
const { effectiveColumns, resetColumnsOrder, resetColumnsToggle } = useDataTableColumns({
key,
columns: [
{ accessor: 'name', width: '40%', toggleable: true, draggable: true, sortable: true },
{ accessor: 'streetAddress', width: '60%', toggleable: true, draggable: true },
{ accessor: 'city', width: 160, toggleable: true, draggable: true },
{ accessor: 'state', textAlign: 'right' },
],
});
return (
<DataTable
withTableBorder
withColumnBorders
storeColumnsKey={key}
records={records}
columns={effectiveColumns}
sortStatus={sortStatus}
onSortStatusChange={setSortStatus}
onRowContextMenu={({ event }) =>
showContextMenu([
{
key: 'reset-toggled-columns',
icon: <IconColumnRemove size={16} />,
onClick: resetColumnsToggle,
},
{
key: 'reset-columns-order',
icon: <IconColumns3 size={16} />,
onClick: resetColumnsOrder,
},
])(event)
}
/>
);
}