Skip to main content

Selection and navigation

Cell, range, row, and column selection share one model and work with pointer, keyboard, clipboard, export, and API workflows.

Loading interactive example…
React
<Grid
rowData={rows}
columnDefs={columns}
rowNumbers
rowSelection
selectAllRowsOnHeaderClick
rangeSelection
highlightActiveCell
onSelectionChanged={({ snapshot }) => console.log(snapshot)}
/>

Selection modes

  • cellSelection: true enables grid focus and selection.
  • cellSelection: "text" restores native browser text selection. Both "text" and false also disable the body keyboard cursor: navigation, clipboard, and editing keys operate on the cursor, so they go with it (keyboard row selection included). The header keyboard cursor stays — disable it separately with headerKeyboardNavigation: false if the grid is deliberately inert.
  • rangeSelection enables drag and Shift-extension.
  • rowSelection uses the row-number cells for row selection.
  • rowSelection: { mode: "multiple", checkboxes: true } adds a dedicated checkbox column (independent of rowNumbers): click toggles the row — always additive, never clearing the rest — and Shift+click unions a range in. A tri-state select-all checkbox renders in its header (disable with headerCheckbox: false), covering the select-all scope (selectAllScope). Use mode: "single" to keep at most one row selected; single mode always hides the header checkbox.
  • The checkbox column starts pinned left. Set checkboxColumnPinned to "right" or null to change its initial position, and set checkboxColumnPinnable: false to lock it there. These are separate options, so any initial position can be either fixed or user-changeable.
  • columnSelection uses headers for column selection.

Arrow keys navigate one cell. Home/End, Page Up/Down, Ctrl/Cmd+Arrow block jumps, and Ctrl/Cmd+Home/End corner jumps keep the active cell visible. Ctrl/Cmd+A selects the full unified row sequence.

On the header cursor, Space selects the column, Ctrl/Cmd+Space adds one to the selection, and Shift+Arrow (or Shift+Home/Shift+End) extends the selection from the cursor's column — but only while the cursor is on a selected column, so a Shift chord never reads as plain movement that starts selecting.

The API exposes focused-cell, range, row, column, navigation, and selection snapshot operations. Pagination invalidates a range from the previous page.

// Rows
api.selectRow(3, "replace");
api.selectAllRows();
console.log(api.getSelectedRows());
api.deselectAllRows();

// Columns (columnSelection: true)
api.selectColumn("revenue", "replace");
api.selectColumn("cost", "toggle");

// Ranges
api.selectRange(2, 1); // row index 2, column index 1
api.extendRangeTo(8, 3);
console.log(api.getSelection());
api.clearSelection("range");

// Keyboard-style navigation
api.setFocusedCell(0, 0);
api.navigate("down");
api.navigate("right", { extend: true });
api.navigate("down", { jump: "block" });
api.navigate("down", { jump: "page", pageRows: 20 });
api.navigateToCorner("bottomRight");

Row selection for an external owner

Row selection is keyed by stable row id, so an application store can drive it directly:

api.selectRowsById(["r1", "r7"]); // replace the selection
api.selectRowsById(["r9"], "add"); // extend it
api.selectRowsById(["r1"], "remove"); // shrink it
api.getSelection().selectedRowIds; // read it back

Unknown or non-selectable ids are dropped (client-side row model). Rows that are currently filtered out can still be selected by id. Programmatic changes emit selectionChanged with reason: "api"; pointer/keyboard interactions report "mouse"/"keyboard", and filter/sort-driven clears report "model". The event's delta: { added, removed } lists row-id membership changes since the previous selection event, so an external owner can update incrementally. Client-side transactions and row-data replacements automatically remove selected ids for rows that no longer exist and report that delta as a model change.

Select-all scope. api.selectAllRows(), api.areAllRowsSelected(), and the row-number header click cover the whole filtered set — all pages — by default. Set selectAllScope: "page" for page-only select-all. On the server-side row model, "filtered" covers loaded rows.

Persistence. By default a filter, sort, or quick-filter change clears the row selection. Set selectionPersistence: "keep" to retain selected row ids across model changes — selection is id-based, so it survives rows moving pages or temporarily leaving the filtered view (the cell range is still cleared, and a selectionChanged with reason: "model" still fires). Exports with scope: "selection" honor the full cross-page selection.