useDataTable
Hook that manages tabular data with sort, filter, pagination, selection, expansion, editing, column/row reorder, resize, and tree-mode flattening.
| Code | Name | Category | Price |
|---|
Usage#
import { useDataTable } from '@primereact/headless/datatable';const dt = useDataTable({ data, dataKey: 'id' });
const { state, rootProps, tableContainerProps, tableProps, getRowKey, sort, selection, pagination, expansion, filter, editing, columnReorder, columnResize, rowReorder, exportData, keyboard } = dt;useDataTable is a single composite hook: every feature (sort, filter, pagination, selection, expansion, editing, etc.) is composed inside it and exposed under a namespaced key. See Primitive for a component-based API.
Features#
- Sort, single, multi, and removable tri-state via
sortField,sortOrder, andmultiSortMeta - Filter, row and menu filters per column with multiple constraints and AND/OR operators, plus a global filter across selected fields
- Pagination, built-in slicing or lazy mode with
totalRecordsandonLazyLoad - Selection, single, multiple (checkbox or row), radio, Shift-range, Ctrl/Meta additive, and indeterminate parents in tree mode
- Expansion, flat row expanders or tree-mode flattening; rows are stamped with
_treeLevel,_treeHasChildren,_treePosInSet,_treeSetSize - Editing,
cellandrowmodes;editingKeysandeditingCellcan be controlled, save and cancel events fire as expected - Column reorder & resize, drag-and-drop reorder,
fitorexpandresize, with hooks for both indicators - Row reorder, drag-and-drop driven from a row handle
- Grouping, group metadata map keyed by row index for grouped headers and row spans
- Tree mode, the same API works on hierarchical data; sort, filter, pagination, and selection all operate tree-aware
- CSV export, export visible, selected, or all rows with custom fields and headers
- Keyboard navigation, arrows (with Shift to extend selection), Home / End, Arrow Left / Right to collapse / expand a tree row, Enter or Space to select, Enter on a row to open the first editable cell
Working with callbacks#
Controlled selection#
Pass selectionKeys and onSelectionChange to drive the selection from outside state.
const [selectionKeys, setSelectionKeys] = React.useState({});
const dt = useDataTable({
data,
dataKey: 'id',
selectionMode: 'multiple',
selectionKeys,
onSelectionChange: (e) => setSelectionKeys(e.value)
});Controlled sort#
Mix single and multi-sort by reading both sortField / sortOrder and multiSortMeta from state.
const [sortField, setSortField] = React.useState<string>();
const [sortOrder, setSortOrder] = React.useState<1 | -1 | 0>();
const dt = useDataTable({
data,
sortField,
sortOrder,
onSortChange: (e) => {
setSortField(e.field);
setSortOrder(e.order);
}
});Controlled filter#
Filters are a record of { value, matchMode, constraints?, operator? }. Both the per-column metadata and the global filter are debounceable via filterDelay.
const [filters, setFilters] = React.useState({
name: { value: null, matchMode: 'contains' },
price: { value: null, matchMode: 'gte' }
});
const [globalFilter, setGlobalFilter] = React.useState('');
const dt = useDataTable({
data,
filters,
onFilter: (e) => setFilters(e.filters),
globalFilter,
globalFilterFields: ['name', 'category'],
filterDelay: 200
});Lazy loading#
In lazy mode the consumer drives data fetching. The hook returns the data as-is and emits onLazyLoad whenever page, sort, or filter state changes.
const dt = useDataTable({
data,
lazy: true,
paginator: true,
totalRecords,
onLazyLoad: (e) => fetchPage(e)
});Tree mode#
Pass nodes with key, data, and optional children; flip treeMode. The hook flattens visible nodes (respecting expandedKeys), and stamps each row with _treeLevel, _treeHasChildren, _treePosInSet, _treeSetSize so the renderer can draw indentation, expanders, and ARIA aria-level / aria-posinset.
const dt = useDataTable({
data: nodes,
treeMode: true,
dataKey: 'key',
expandedKeys,
onExpandedChange: (e) => setExpandedKeys(e.value)
});Cell and row editing#
const dt = useDataTable({
data,
editMode: 'cell',
onCellEditComplete: (e) => {
// mutate `data` based on `e.rowData`, `e.field`, `e.newValue`, and call `e.preventDefault()` to keep the cell open
}
});Switch to editMode="row" and use onRowEditSave / onRowEditCancel for whole-row commits.
Per-row state with useDataTableRow#
For hooking up a single <tr> to selection / expansion / reorder / editing, pair useDataTable with useDataTableRow. It returns a single rowProps getter pre-wired with role, aria-rowindex, click / key handlers, drag handlers when reorder is active, plus tree-mode ARIA (aria-level, aria-expanded, aria-posinset, aria-setsize).
import { useDataTable, useDataTableRow } from '@primereact/headless/datatable';
const dt = useDataTable({ data, dataKey: 'id', selectionMode: 'multiple' });
function Row({ item, index }) {
const row = useDataTableRow({ item, index, context: dt });
return <tr {...row.rowProps}>{/* cells */}</tr>;
}Styling with data attributes#
Every part exposes its state through data-* attributes, drive your CSS from those instead of class toggles.
| Scope | Part | States |
|---|---|---|
datatable | root | data-loading, data-row-hover, data-highlight-on-select, data-selection-mode, data-size, data-striped-rows, data-show-gridlines |
datatable | table-container | |
datatable | table | |
datatable | row | data-index, data-selected, data-drag-source, data-dragpoint-top, data-dragpoint-bottom |
datatable | sort | data-sorted, data-unsorted, data-sort-order (asc / desc) |
datatable | filter | data-display (row / menu), data-active |
datatable | cell-editor | data-row-index, data-field, data-row-key, data-editing |
datatable | row-toggle | data-tree-level, aria-expanded |
datatable | column-resizer |
[data-scope='datatable'][data-part='row'][data-selected] {
background: var(--p-primary-50);
}
[data-scope='datatable'][data-part='sort'][data-sort-order='asc']::after {
content: '↑';
}
[data-scope='datatable'][data-part='cell-editor'][data-editing] {
outline: 2px solid var(--p-primary-color);
}
[data-scope='datatable'][data-part='row'][data-dragpoint-top] {
box-shadow: 0 -2px 0 var(--p-primary-color) inset;
}API#
useDataTable#
| Name | Type | Default |
|---|---|---|
useDataTableRow#
Accessibility#
role="table" is applied for flat data and role="treegrid" when treeMode is enabled. Each row exposes aria-rowindex (1-based) and, in tree mode, aria-level, aria-expanded, aria-posinset, and aria-setsize. Sort triggers expose role="button", aria-sort, and a descriptive aria-label. Cell-edit wrappers tag their <td> with data-editable-cell so Tab traversal can find and focus the next editable cell. See Primitive for full WAI-ARIA compliance details.