Row selection
Letting the user select whole rows with selectable.rows.
Last updated August 24, 2026
selectable.rows takes a SelectionMode — false, "single", or "multiple" — off by default, since selection claims the click a display-only grid shouldn't. Give getRowId alongside it for data that sorts, filters, or pages; without one a row is identified by its position, so a re-sort leaves the same positions selected under different rows.
Multi-select rows#
selectable={{ rows: "multiple" }}
Live exampleThis example runs as a real project on StackBlitz.
<DataGridComponent
columns={columns}
dataSource={rows}
getRowId={(row) => String(row.Id)}
selectable={{ rows: "multiple" }}
onRowSelectionChange={({ selected }) => persist(selected)}
/>;Props#
| Prop | Type | Default | Description |
|---|---|---|---|
selectable.rows | false | "single" | "multiple" | false | How many rows the user may select at once. |
getRowId | (row: Row, index: number) => string | row position | A row's stable identity. Give one for data that sorts, filters, or pages, or a selection follows the position rather than the row. |
defaultRowSelection | SelectionState | Row ids selected to start with, keyed as getRowId resolves them. Uncontrolled. | |
onRowSelect / onRowsSelect | (event) => void | Once per row newly selected, and once per interaction with every row it selected. | |
onRowDeselect / onRowsDeselect | (event) => void | The deselecting counterpart of each, above. | |
onRowSelectionChange | (event: RowSelectionChangeEvent) => void | Once per change with what it added, what it removed, and everything selected after — the one to persist from. |
Payload shape#
RowSelectionChangeEvent<Row> — the payload of onRowSelectionChange, and the one to persist from:
| Field | Type | Description |
|---|---|---|
added | readonly ResolvedRow<Row>[] | Rows this interaction newly selected. |
removed | readonly ResolvedRow<Row>[] | Rows this interaction deselected. |
selected | readonly ResolvedRow<Row>[] | Every selected row, not only what this interaction changed. |
selection | SelectionState | The same rows, as ids only — readonly string[]. |
See imperative handle for ResolvedRow<Row>'s own fields. onRowSelect/onRowsSelect/onRowDeselect/onRowsDeselect fire the row(s) they name, each as a ResolvedRow<Row>, alongside the selection at that point.
Reading selection outside the grid's own tree#
useSelectionState subscribes to row, column, and cell selection together through the grid's ref — one combined hook, not three, matching how the grid treats all three as one concern internally — for a "N rows selected" toolbar living elsewhere on the page:
import { useRef } from "react";
import {
DataGridComponent,
useSelectionState,
type DataGridApi,
} from "@gridkitjs/react";
function Toolbar({ gridRef }: { gridRef: RefObject<DataGridApi<Row> | null> }) {
const { rowSelection, clearSelection, selectAllRows } =
useSelectionState(gridRef);
return (
<div className="my-toolbar">
<span>{rowSelection.length} row(s) selected</span>
<button onClick={selectAllRows}>Select all</button>
<button onClick={clearSelection}>Clear</button>
</div>
);
}| Field | Type | Description |
|---|---|---|
rowSelection | SelectionState | Selected row ids. |
columnSelection | SelectionState | Selected column ids — see column selection. |
cellSelection | CellSelectionState | The selected cell, if any — see cell selection. |
clearSelection | () => void | Clears row, column, and cell selection together. |
selectAllRows | () => void | Selects every row. |
Before the grid mounts, the row/column fields read as empty arrays and the cell field reads null. See imperative handle for subscribe, the primitive this hook is built on.