Row Selection
Checkbox selection for one row or many, with a select-all across every filtered page. The table owns the selected set until you pass selectedIds.
Selection Modes
selectionMode switches on a checkbox column. "multi" lets the user mark any number of rows and adds
a select-all checkbox to the header. "single" keeps one
row at a time: selecting a row clears the one before. The default, "none", is the table without a checkbox column.
Select-all covers every row that matches the current search and filters, on every page, not just the rows on screen. While only part of that set is selected, the checkbox shows as indeterminate.
The selection is a set of ids, keyed by item.id, or by
the row's position in the items array you passed when a
row has none. Sorting, paging and filtering change what is on screen, not the set: a selected
row that moves to another page stays selected. onSelectionChange reports each change, with the selected
rows and their ids; paging or sorting is not a change and does not fire it.
Live — select-all spans both pages
Name | Role | Department | Location | |
|---|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin | |
Liam Chen | Product Designer | Design | Hamburg | |
Sofia Martinez | Engineering Manager | Platform | Munich | |
James Park | Frontend Developer | Product | Remote |
0 selected
<script lang="ts">
let selected = $state<Employee[]>([]);
</script>
<Table
{items}
{columns}
selectionMode="multi"
viewDefaults={{ pageSize: 4 }}
onSelectionChange={(items) => (selected = items)}
/>
<p>{selected.length} selected</p>Selecting by Row Click
In "single" mode a click anywhere on the row selects
it: the checkbox is not the only target. In "multi" mode, and wherever onRowClick or expandable rows already give a click
another meaning, only the checkbox selects. rowClickSelects decides it explicitly in either mode.
Single select — click the row
Name | Role | Department | Location | |
|---|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin | |
Liam Chen | Product Designer | Design | Hamburg | |
Sofia Martinez | Engineering Manager | Platform | Munich | |
James Park | Frontend Developer | Product | Remote |
<Table
{items}
{columns}
selectionMode="single"
onSelectionChange={(items) => handleSelect(items[0])}
/>A row you only show somewhere else, the master/detail pattern, is not a selection. activeRowId highlights the row your onRowClick handler opened, without bringing the checkbox
column along.
Controlled Selection
The table owns the selection until you pass selectedIds, from then on your code does. Take it over
when the set has a life outside the table: preselected from the URL, cleared after a bulk
action, shared with another view. If all you need is a starting value, initialSelectedIds={[1, 3]} seeds the table-owned
selection once. Later changes to that prop are ignored, and it is ignored altogether when selectedIds is set.
Every value you pass in selectedIds becomes the table's
selection, and clicks keep arriving through onSelectionChange, which hands you the selected rows
and their ids. Write the ids back: they are always the whole selection, while the
rows can only be the ones the table currently holds — under server processing that is one page, so mapping the rows would drop everything selected on another page. An empty array
is a valid value (nothing selected); undefined hands the selection back to the table. Your
own writes fire onSelectionChange as well, and writing
the same ids back is a no-op, so the Clear button below settles rather than looping. A
controlled selection is never written to storage: persistSelection in the preference channel restores only a table-owned one.
Controlled — buttons and checkboxes write the same set
Name | Role | Department | Location | |
|---|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin | |
Liam Chen | Product Designer | Design | Hamburg | |
Sofia Martinez | Engineering Manager | Platform | Munich | |
James Park | Frontend Developer | Product | Remote | |
Aisha Patel | Data Scientist | Data | Berlin | |
Noah Kim | DevOps Engineer | Platform | Hamburg |
<script lang="ts">
let selectedIds = $state<Array<string | number>>([1, 3]);
</script>
<Table
{items}
{columns}
selectionMode="multi"
{selectedIds}
onSelectionChange={(items, ids) => (selectedIds = ids)}
/>
<Button onclick={() => (selectedIds = [])}>Clear selection</Button>Write every change back
WhenonSelectionChange does not feed selectedIds, clicks still change the screen and nothing warns; the next change
to the prop then throws the user's clicks away.