DataTable
DataTable displays data in tabular format with sorting, filtering, pagination and selection features.
| Product | Category | Price | Rating | Status |
|---|
Usage#
import { DataTable } from '@primereact/ui/datatable';<DataTable.Root data={data}>
<DataTable.Header />
<DataTable.TableContainer>
<DataTable.Table>
<DataTable.THead>
<DataTable.THeadRow>
<DataTable.THeadCell>Column</DataTable.THeadCell>
</DataTable.THeadRow>
</DataTable.THead>
<DataTable.TBody>
{({ item }) => (
<DataTable.Row>
<DataTable.Cell>{item.field}</DataTable.Cell>
</DataTable.Row>
)}
</DataTable.TBody>
</DataTable.Table>
</DataTable.TableContainer>
<DataTable.Footer />
</DataTable.Root>DataTable.Header and DataTable.Footer are optional sibling slots around DataTable.TableContainer (which is the scrollable wrapper around DataTable.Table).
For hierarchical data, see TreeTable — a sibling component that exposes the same features over a tree structure.
Examples#
Basic#
Displays a list of items in tabular format.
Size#
Use the size prop with small or large to adjust cell padding. Omit for the default size.
<DataTable.Root size="small">...</DataTable.Root>Gridlines#
Enable the showGridlines prop to render borders between cells.
<DataTable.Root showGridlines>...</DataTable.Root>Striped Rows#
The stripedRows prop renders rows with alternating background colors.
<DataTable.Root stripedRows>...</DataTable.Root>Selection#
Row selection is driven by the selectionMode prop (single or multiple). The selectedKeys prop holds a map of selected row keys and onSelectionChange fires when the selection changes. When metaKeySelection is enabled, Ctrl/Cmd + Click toggles rows and Shift + Click selects a range. For checkbox- and radio-driven UIs, the DataTable.Selection render prop exposes isSelected / toggle at row level and isAllSelected / isSomeSelected / toggleAll at header level.
<DataTable.Root data={data} dataKey="id" selectionMode="multiple" selectedKeys={selectedKeys} onSelectionChange={(e) => setSelectedKeys(e.value)}>
...
</DataTable.Root>Single#
One row at a time. Clicking a different row replaces the previous selection.
Multiple#
Multiple rows without a dedicated column. Pair with metaKeySelection so Ctrl/Cmd + Click toggles rows and Shift + Click selects a range; a plain click still replaces the selection.
Checkbox#
Checkbox-based multiple selection with a header select-all. Use the Selection render prop to wire isSelected / toggle for row-level and isAllSelected / isSomeSelected / toggleAll for the header.
Radio#
Radio-based single selection. Combine selectionMode="single" with the Selection render prop in mode="radio" on the first cell.
Keyboard#
Arrow Up/Down moves focus between rows, Space or Enter toggles the focused row, and Shift + Arrow extends a range. Paired with selectionMode="multiple" and metaKeySelection, the whole flow is keyboard-driven.
Sort#
Wrap a column header with DataTable.Sort field="…" to make it sortable. Inside, DataTable.SortIndicator match="asc | desc | unsorted" renders direction icons and DataTable.SortOrder shows the priority badge in multi-sort mode. Use removableSort to let headers cycle back to the unsorted state.
<DataTable.Root data={data} dataKey="id" removableSort>
<DataTable.THeadCell>
<DataTable.Sort field="name">
Name
<DataTable.SortIndicator match="asc">▲</DataTable.SortIndicator>
<DataTable.SortIndicator match="desc">▼</DataTable.SortIndicator>
<DataTable.SortOrder />
</DataTable.Sort>
</DataTable.THeadCell>
...
</DataTable.Root>Single#
Clicking a column header cycles through ascending, descending, and unsorted.
Multiple#
Hold Ctrl/Cmd and click multiple column headers to sort by several fields at once. Each sorted column shows its direction via SortIndicator and its priority via SortOrder.
Presort#
Apply an initial sort on mount. Use defaultSortField + defaultSortOrder for a single column; headers stay interactive afterwards.
<DataTable.Root data={data} dataKey="id" defaultSortField="price" defaultSortOrder={-1} removableSort>
...
</DataTable.Root>For multi-column presort, use defaultMultiSortMeta (uncontrolled). Each entry defines a field and direction (1 ascending, -1 descending); array order is the sort priority. For fully controlled behaviour, use multiSortMeta with onSortChange instead.
<DataTable.Root
data={data}
dataKey="id"
defaultMultiSortMeta={[
{ field: 'category', order: 1 },
{ field: 'price', order: -1 }
]}
removableSort
>
...
</DataTable.Root>Pagination#
DataTable exposes pagination state via render prop, allowing complete control over the pagination UI.
Scroll#
Set scrollable on DataTable.Root to enable scrolling inside DataTable.TableContainer; the thead stays sticky at the top. Pair with scrollHeight to cap the viewport or let the container grow with its content.
Vertical#
A fixed scrollHeight enables vertical scrolling with a sticky header. Works well when the dataset is taller than the surrounding card.
Horizontal#
When the combined column widths exceed the container, the table scrolls horizontally. Give each column a minWidth so the columns don't squeeze.
Flex#
scrollHeight="flex" lets the viewport grow and shrink with its flex parent — handy inside resizable dialogs or split layouts.
Frozen Columns#
Add frozen to a DataTable.Column to pin it during horizontal scroll. Pinned columns stick to the left edge while the rest scrolls underneath.
Multiple columns can be frozen on both sides — pass frozenAlignment="right" to pin to the right edge.
Frozen Rows#
Render a DataTable.FrozenTBody above the regular DataTable.TBody to keep specific rows pinned to the top while the rest of the dataset scrolls.
Row Expansion#
Expand rows to show additional detail content. Use RowToggle with RowToggleIndicator for expand/collapse icons.
Editing#
DataTable supports two edit modes via the editMode prop: cell for inline cell-by-cell editing and row for committing a full row at once. Editing state is keyed by the row key in both modes.
Cell#
Inline cell editing with CellEditor, CellEditorDisplay and CellEditorContent sub-components following the Inplace pattern. Use editMode="cell" on DataTable.Root and handle committed values in onCellEditComplete.
Cell editing composes with row selection: clicks inside an editable cell start editing, clicks elsewhere on the row drive selection. With a row focused, Enter opens its first editable cell; Space still toggles the selection.
Row#
Row-level editing with RowEditor, RowEditorInit, RowEditorSave and RowEditorCancel action components. Use editMode="row" on DataTable.Root with controlled editingKeys + onEditingKeysChange; the onRowEditSave / onRowEditCancel events fire with the final row data.
Row Grouping#
Group rows by a field value with RowGroupHeader and RowGroupFooter for group headers and footers. Grouping operates on contiguous rows, so pair groupField with defaultSortField (or an active sort on the same field) to lay out the data in groups before rendering.
For a spreadsheet-style layout, skip the group header/footer and merge the group column vertically using rowSpan={groupMeta.groupCount} on the first row of each group.
Column Resize#
Enable column resizing with drag handles via the resizableColumns prop. Two modes are supported via columnResizeMode:
fit(default): dragging a column takes width from the adjacent column; total table width stays the same.expand: dragging grows or shrinks the whole table; adjacent columns keep their widths. Usually paired withscrollableso the table can exceed its viewport.
Both demos enable showGridlines to make the effect visible.
Fit Mode#
Expand Mode#
Column Reorder#
Drag and drop column headers to reorder columns.
Row Reorder#
Drag and drop rows to reorder data.
Column Toggle#
Show/hide columns dynamically.
Column Group#
Multi-level headers with rowspan and colspan.
Sort and filter work on any leaf header cell in a grouped layout — wrap the header in DataTable.Sort and add a filter row below the leaf row.
Filter#
Filtering is driven by a filters object passed to DataTable.Root; each column wraps its filter UI with DataTable.Filter and receives render-prop helpers (value, match mode, constraints, overlay state, …). Global search is opt-in via globalFilter + globalFilterFields.
Basic#
display="row" renders inline inputs directly under each column header and applies immediately as the user types. Pair with a global InputText in a header slot for keyword search.
Advanced#
display="menu" swaps the inline input for a trigger icon that opens a popover. Each field supports multiple constraints joined by an AND/OR operator, a match mode per constraint, and Apply/Clear actions.
Export#
Export table data to CSV with customizable fields and headers.
Lazy Loading#
Server-side data loading with pagination integration.
Loading#
Two patterns for displaying a loading state while data is being fetched.
Overlay#
Set the loading prop on DataTable.Root and provide a spinner inside DataTable.Loading. An absolutely positioned overlay dims the table and shows the indicator.
Skeleton#
Render placeholder rows filled with Skeleton elements while the request is in flight. This keeps the row layout stable and avoids an overlay that covers existing content.
Empty State#
Custom empty state when no data is available, using EmptyTBody.
Advanced#
Sort, filter (per-column + global), and cell editing composed in a single table.
API#
Sub-Components#
See DataTable Primitive for the full sub-component API.
Hooks#
See useDataTable for the headless hook API.
Accessibility#
See DataTable Primitive for WAI-ARIA compliance details and keyboard support.