selectable: true adds a checkbox column (SelectableRows plugin). Set
singleSelect: true for radio buttons instead (implies selectable).
Selection is server-first and lives in the core as a SelectionState:
// explicit: the selected row keys are in `ids`
{ mode: "explicit", ids: Set(["1", "2"]), except: Set() }
// all: every matching row is selected except the ones in `except`
{ mode: "all", ids: Set(), except: Set(["3"]) }selectAll() uses mode: "all" when selectVisibleOnly is false, so a
select-all across server pages only needs the keys of the rows you want to
exclude. With selectVisibleOnly: true (default) it only selects the visible
page as an explicit ids set.
Row keys come from the rowKey option ("id" by default), either a field name
or a function (row) => key.
Every row control (checkbox or radio) is labelled Select <row label>, and the
header control is labelled with the selectAll label. The row label comes from
the rowLabel option, a field name or a function (row, index) => string,
falling back to the row key, then the row index:
const grid = new DataGrid({
selectable: true,
rowLabel: "name", // -> "Select Alice Smith"
// rowLabel: (row) => `${row.first} ${row.last}`,
});getRowLabel(row, index) exposes the resolver publicly.
grid.isRowSelected(row, index) // boolean
grid.getSelectionState() // { mode, ids, except } snapshot
grid.selectRow(row, index)
grid.deselectRow(row, index)
grid.toggleRow(row, index)
grid.selectAll() // visible page, or everything when selectVisibleOnly is false
grid.clearSelection()getSelection(...keys) is a page-local convenience: with no keys it returns the
selected row objects of the current page, with one key an array of values, with
several keys an array of objects.
grid.addEventListener("selectionChange", (ev) => {
console.log(ev.detail.selectionState);
});The core owns the tr[data-selected] state attribute; the plugin only renders
the checkboxes.
Selection survives pagination and sorting, but any population change clears
it: a mode: "all" selection only means something for the population it was
created on. Changing the global search or the column filters (and switching the
data source) invalidates the selection. The selection is also cleared as soon as
the search input value changes, even before the new search is committed, so a
bulk action never targets the population of a previous search.
rowClick: "select" turns every data row into a click target that toggles its
selection:
const grid = new DataGrid({
selectable: true,
rowClick: "select",
});The whole row becomes a large mouse/touch target, while the native checkbox (or
radio with singleSelect) remains the keyboard and accessibility interface.
Rows only get the dg-clickable-row class (cursor) when selectable is on.
Interactive elements inside a row (a, button, input, select, textarea,
[contenteditable]:not([contenteditable="false"]), [data-row-click-ignore])
and the selection control itself never trigger the toggle.
A cancelable rowClick event fires before the toggle and can veto it:
grid.addEventListener("rowClick", (ev) => {
if (ev.detail.row.protected) {
ev.preventDefault();
}
});bulkActions adds a permanent bar with one button per action. A
.dg-selection-count badge shows the plain selected count and is hidden while
nothing is selected; the buttons are disabled until the count reaches one.
The badge announces selectedCount ("3 selected") through a live region while
staying visually language-neutral:
const grid = new DataGrid({
selectable: true,
bulkActions: [
{ name: "archive", label: "Archive", intent: "danger" },
],
});
grid.addEventListener("bulkAction", (ev) => {
// { action, selection, query }
console.log(ev.detail.action, ev.detail.selection, ev.detail.query);
});Unlike row actions, a bulk action receives the whole SelectionState and the
current QueryState, so it can act server-side on any number of rows.