useTreeTable
Hierarchical data table built on useDataTable with treeMode enabled — sort, filter, paginate, select, expand, and edit tree-shaped data.
| Name | Size | Type |
|---|
Usage#
TreeTable is not a separate hook — it is useDataTable with treeMode: true. The hook flattens the visible part of the tree (respecting expandedKeys), so every other feature (sort, filter, pagination, selection, editing, reorder, export) works the same way as on flat data.
import { useDataTable } from '@primereact/headless/datatable';const tree = useDataTable({
data: nodes,
dataKey: 'key',
treeMode: true,
expandedKeys,
onExpandedChange: (e) => setExpandedKeys(e.value)
});Nodes are objects of the shape { key, data, children? }. Flat rows produced by the hook are stamped with helpers used by the renderer:
| Field | Type | Meaning |
|---|---|---|
_treeLevel | number | Zero-based depth in the tree (used for indentation and aria-level). |
_treeHasChildren | boolean | Whether the row has children (drives the expander vs. spacer). |
_treePosInSet | number | One-based position among siblings (aria-posinset). |
_treeSetSize | number | Total siblings at this depth (aria-setsize). |
Features#
All useDataTable features work the same way; the table role becomes treegrid and rows pick up tree-aware ARIA attributes. A few things behave differently in tree mode:
- Filter — column filters and the global filter keep ancestor nodes when any descendant matches, so the result stays connected to its roots
- Selection — checkbox selection cascades to descendants; partially-selected parents are reported through
selection.isPartiallySelected(key) - Pagination — the paginator slices root-level nodes only; expanded children stay inside the same page
Working with callbacks#
Controlled expansion#
const [expandedKeys, setExpandedKeys] = React.useState<Record<string, boolean>>({ '0': true });
const tree = useDataTable({
data: nodes,
dataKey: 'key',
treeMode: true,
expandedKeys,
onExpandedChange: (e) => setExpandedKeys(e.value)
});Filter + sort + pagination#
Pass the same filters / sortField / paginator props as on a flat DataTable; the hook re-runs them against the tree.
const tree = useDataTable({
data: nodes,
treeMode: true,
paginator: true,
rows: 10,
filters,
onFilter: (e) => setFilters(e.filters),
sortField,
sortOrder,
onSortChange: (e) => {
setSortField(e.field);
setSortOrder(e.order);
}
});API#
useDataTable#
| Name | Type | Default |
|---|---|---|
data | Record<string, unknown>[] | object[] | — |
| An array of objects to display. | ||
defaultValue | string | — |
| Default sort value for uncontrolled mode. | ||
value | string | — |
| Sort field value for controlled mode. | ||
dataKey | string | — |
| A property to uniquely identify each row in the data. | ||
loading | boolean | false |
| Whether the data is currently being loaded. | ||
lazy | boolean | false |
| Defines if data is loaded and interacted with in lazy manner. | ||
totalRecords | number | 0 |
| Number of total records, used in lazy mode. | ||
scrollable | boolean | false |
| When enabled, the table can be scrolled horizontally and/or vertically. | ||
scrollHeight | string | — |
| Height of the scroll viewport in fixed pixels or the "flex" keyword for a dynamic size. | ||
sortField | string | undefined |
| Property name to sort by in single-sort mode. | ||
sortOrder | SortOrder | undefined |
| Sort order for single-sort mode. | ||
defaultSortField | string | undefined |
| Default sort field for uncontrolled single-sort mode. | ||
defaultSortOrder | SortOrder | undefined |
| Default sort order for uncontrolled single-sort mode. | ||
multiSortMeta | SortMeta[] | undefined |
| An array of SortMeta objects for multi-column sorting (controlled). | ||
defaultMultiSortMeta | SortMeta[] | undefined |
| Initial multi-column sort metadata for uncontrolled mode. | ||
onSortChange | (event: DataTableSortEvent) => void | — |
| Callback invoked when the sort state changes. | ||
removableSort | boolean | false |
| When true, clicking a sorted column header a third time removes the sort. | ||
nullSortOrder | number | 1 |
| Determines where null values are placed during sort. 1 = nulls last (default), -1 = nulls first. | ||
selectionMode | "multiple" | "single" | — |
| Defines the selection mode. 'single' allows one row, 'multiple' allows many. | ||
metaKeySelection | boolean | false |
| When true, row click selection requires Ctrl/Cmd key. Without it, click selects only that row. Shift+Click extends range. Only applies when selectionMode is set. | ||
selectedKeys | SelectionKeys | undefined |
| The selection keys for controlled mode. | ||
defaultSelectedKeys | SelectionKeys | undefined |
| The default selection keys for uncontrolled mode. | ||
onSelectionChange | (event: DataTableSelectionEvent) => void | undefined |
| Callback invoked when the selection changes. | ||
page | number | undefined |
| Current page number for controlled pagination (0-indexed). | ||
defaultPage | number | 0 |
| Default page number for uncontrolled pagination (0-indexed). | ||
rows | number | undefined |
| Number of rows to display per page for controlled mode. | ||
defaultRows | number | 10 |
| Default number of rows to display per page for uncontrolled mode. | ||
rowsPerPageOptions | number[] | undefined |
| Array of integer values to display inside the rows per page dropdown. | ||
paginator | boolean | false |
| Whether pagination is enabled. | ||
onPageChange | (event: DataTablePageEvent) => void | — |
| Callback invoked when the page or rows per page changes. | ||
expandedKeys | ExpandedKeys | undefined |
| The expanded keys map for controlled row expansion. | ||
defaultExpandedKeys | ExpandedKeys | undefined |
| The default expanded keys map for uncontrolled row expansion. | ||
onExpandedChange | (event: DataTableExpansionEvent) => void | — |
| Callback invoked when the expanded keys change. | ||
groupField | string | undefined |
| The field name to group rows by. | ||
reorderableColumns | boolean | false |
| When enabled, columns can be reordered using drag and drop. | ||
onColumnReorder | (event: DataTableColumnReorderEvent) => void | — |
| Callback invoked when columns are reordered. | ||
resizableColumns | boolean | false |
| When enabled, columns can be resized using drag and drop. | ||
columnResizeMode | ColumnResizeMode | 'fit' |
| Defines whether the overall table width should change on column resize. 'fit' mode keeps total width the same. 'expand' mode increases total width. | ||
onColumnResizeEnd | (event: DataTableColumnResizeEvent) => void | — |
| Callback invoked when a column resize ends. | ||
editMode | DataTableEditMode | undefined |
| Defines the editing mode. | ||
editingKeys | EditingKeys | undefined |
| The editing keys map for controlled row editing. | ||
defaultEditingKeys | EditingKeys | undefined |
| The default editing keys for uncontrolled row editing. | ||
onEditingKeysChange | (event: DataTableEditingEvent) => void | — |
| Callback invoked when the editing keys change. | ||
onRowEditInit | (event: DataTableRowEditEvent) => void | — |
| Callback invoked when a row edit is initiated. | ||
onRowEditSave | (event: DataTableRowEditEvent) => void | — |
| Callback invoked when a row edit is saved. | ||
onRowEditCancel | (event: DataTableRowEditEvent) => void | — |
| Callback invoked when a row edit is cancelled. | ||
onCellEditInit | (event: { originalEvent: SyntheticEvent; field: string; rowIndex: number }) => void | — |
| Callback invoked when a cell edit is initiated. | ||
onCellEditComplete | (event: DataTableCellEditEvent) => void | — |
| Callback invoked when a cell edit completes. | ||
onCellEditCancel | (event: DataTableCellEditEvent) => void | — |
| Callback invoked when a cell edit is cancelled. | ||
filters | DataTableFilterMeta | undefined |
| Filter metadata for controlled mode. | ||
defaultFilters | DataTableFilterMeta | undefined |
| Default filter metadata for uncontrolled mode. | ||
globalFilter | string | — |
| Global filter value applied across globalFilterFields. | ||
globalFilterFields | string[] | undefined |
| An array of field names to search with globalFilter. | ||
filterDelay | number | 0 |
| Delay in ms before applying filter (for debounce). | ||
onFilter | (event: DataTableFilterEvent) => void | — |
| Callback invoked when filters change. | ||
reorderableRows | boolean | false |
| When enabled, rows can be reordered using drag and drop. | ||
onRowReorder | (event: DataTableRowReorderEvent) => void | — |
| Callback invoked when rows are reordered. | ||
rowClassName | (data: Record<string, unknown>, options: { index: number; props: useDataTableProps }) => string | — |
| A function that returns a className for a given row. | ||
onLazyLoad | (event: DataTableLazyLoadEvent) => void | — |
| Callback invoked when lazy loading is triggered (page, sort, filter change in lazy mode). | ||
onRowClick | (event: DataTableRowMouseEvent) => void | — |
| Callback fired when a row is clicked. Does NOT fire when the click originates on interactive content (buttons, inputs, checkboxes, radios) — those bubble their own semantics. | ||
onRowDoubleClick | (event: DataTableRowMouseEvent) => void | — |
| Callback fired on row double-click. | ||
onRowContextMenu | (event: DataTableRowMouseEvent) => void | — |
| Callback fired on row right-click (contextmenu). Does not prevent the default menu — call `event.originalEvent.preventDefault()` in the handler if you want to. | ||
rowHover | boolean | false |
| When enabled, rows highlight on mouse hover via `data-row-hover` attribute on root. | ||
highlightOnSelect | boolean | true |
| When enabled, selected rows are highlighted via `data-highlight-on-select` attribute on root. | ||
treeMode | boolean | false |
| When enabled, data is treated as a tree structure with `key` , `data` , and `children` fields. Tree nodes are flattened internally and sort, filter, pagination operate on the tree structure. Pagination applies to root-level nodes only. | ||
size | "small" | "large" | undefined |
| Table size variant. Adjusts cell padding and font size via CSS. | ||
stripedRows | boolean | false |
| When enabled, rows are rendered with alternating background colors. | ||
showGridlines | boolean | false |
| When enabled, borders are displayed between cells. | ||
useDataTableRow#
| Name | Type | Default |
|---|---|---|
item | Record<string, unknown> | — |
| The data object for this row. | ||
index | number | 0 |
| The index of the row in the data array. | ||
context | useDataTableInstance | — |
| The parent datatable instance providing state and methods. | ||
Accessibility#
role="treegrid" is applied to the table; rows expose aria-level, aria-expanded, aria-posinset, aria-setsize. Expander buttons emit aria-expanded and a descriptive aria-label. See Primitive for full WAI-ARIA compliance details.