Let users reorder React Data Grid columns by drag-and-drop and hide or show columns through a column chooser.
Give users control over the layout: drag headers to reorder columns and toggle columns on and off to focus on what matters. Both features are driven through the headless table, so you can wire them into your own toolbar — as the column chooser in this demo does.
Column ordering & visibility
columnOrder makes headers draggable — drop one onto another to reorder
(dragging never crosses a pinning boundary); pass an array for an initial order.
columnVisibility enables hiding and showing columns through the headless table
(column.toggleVisibility(), column.getIsVisible()); pass an object like
{ email: false } to start with a column hidden. Opt a column out with
movable: false / hideable: false. This demo adds a column chooser built
entirely with the toolbar slot.
import { CDataGrid } from '@coreui/react-data-grid'
import type { CDataGridSlotProps } from '@coreui/react-data-grid'
import { useMemo } from 'react'
const firstNames = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank', 'Grace', 'Heidi', 'Ivan', 'Judy']
const lastNames = ['Smith', 'Jones', 'Brown', 'Taylor', 'Wilson', 'Davies', 'Evans', 'Thomas']
const roles = ['admin', 'editor', 'viewer']
// Column chooser built with the toolbar slot and the headless table
const ColumnChooser = ({ table }: CDataGridSlotProps) => (
<div className="d-flex gap-3 mb-2">
{table.getAllLeafColumns().map(column =>
column.getCanHide() ?
(
<label key={column.id} className="form-check form-check-inline m-0">
<input
type="checkbox"
className="form-check-input me-1"
checked={column.getIsVisible()}
onChange={event => column.toggleVisibility(event.target.checked)}
/>
{column.id}
</label>
) :
null
)}
</div>
)
export const DataGridOrderVisibilityExample = () => {
const items = useMemo(
() =>
Array.from({ length: 1000 }, (_, i) => {
const name = `${firstNames[i % firstNames.length]} ${lastNames[i % lastNames.length]}`
return {
id: i + 1,
name,
email: `${name.toLowerCase().replace(' ', '.')}${i}@example.com`,
role: roles[i % roles.length]
}
}),
[]
)
return (
<CDataGrid
columns={[
// movable/hideable: false keeps the key column in place
{
key: 'id', label: '#', width: 90, movable: false, hideable: false
},
{ key: 'name', label: 'Name' },
{ key: 'email', label: 'Email', style: { width: '30%' } },
{ key: 'role', label: 'Role', width: 110 }
]}
items={items}
itemKey={item => String(item.id)}
columnOrder
columnVisibility
pagination={{ pageSize: 10 }}
slots={{ toolbar: ColumnChooser }}
/>
)
} import { CDataGrid } from '@coreui/react-data-grid'
import type { CDataGridSlotProps } from '@coreui/react-data-grid'
import { useMemo } from 'react'
const firstNames = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank', 'Grace', 'Heidi', 'Ivan', 'Judy']
const lastNames = ['Smith', 'Jones', 'Brown', 'Taylor', 'Wilson', 'Davies', 'Evans', 'Thomas']
const roles = ['admin', 'editor', 'viewer']
// Column chooser built with the toolbar slot and the headless table
const ColumnChooser = ({ table }: CDataGridSlotProps) => (
<div className="d-flex gap-3 mb-2">
{table.getAllLeafColumns().map(column =>
column.getCanHide() ?
(
<label key={column.id} className="form-check form-check-inline m-0">
<input
type="checkbox"
className="form-check-input me-1"
checked={column.getIsVisible()}
onChange={event => column.toggleVisibility(event.target.checked)}
/>
{column.id}
</label>
) :
null
)}
</div>
)
export const DataGridOrderVisibilityExample = () => {
const items = useMemo(
() =>
Array.from({ length: 1000 }, (_, i) => {
const name = `${firstNames[i % firstNames.length]} ${lastNames[i % lastNames.length]}`
return {
id: i + 1,
name,
email: `${name.toLowerCase().replace(' ', '.')}${i}@example.com`,
role: roles[i % roles.length]
}
}),
[]
)
return (
<CDataGrid
columns={[
// movable/hideable: false keeps the key column in place
{
key: 'id', label: '#', width: 90, movable: false, hideable: false
},
{ key: 'name', label: 'Name' },
{ key: 'email', label: 'Email', style: { width: '30%' } },
{ key: 'role', label: 'Role', width: 110 }
]}
items={items}
itemKey={item => String(item.id)}
columnOrder
columnVisibility
pagination={{ pageSize: 10 }}
slots={{ toolbar: ColumnChooser }}
/>
)
} Options
| Option | Type | Default | Description |
|---|---|---|---|
columnOrder | boolean | string[] | false | Drag-and-drop reordering; an array sets the initial order. Never crosses a pinning boundary. |
columnVisibility | boolean | Record<string, boolean> | false | Enables hiding/showing columns; an object sets the initial visibility. |
movable (column) | boolean | true | Set false to exclude a column from reordering. |
hideable (column) | boolean | true | Set false to prevent hiding a column. |
Reordering calls onOrderChange with the columnOrder state; toggling
visibility calls onVisibilityChange with the columnVisibility state. The
column menu offers a keyboard-accessible Move left/right as an
alternative to drag-and-drop.