addSelectedRows

addSelectedRows keeps track of selected items in the table. Works with sub-rows.

Options

Information:
Options passed into addSelectedRows.
const table = createTable(data, {
  select: addSelectedRows({ ... }),
});
const table = createTable(data, {
  select: addSelectedRows({ ... }),
});

initialSelectedDataIds?: Record<string, boolean>

Initial selected row data ids (by row.dataId). Default {}.

linkDataSubRows?: boolean

Link parent/sub-row selection when updating. Default true.

Column Options

Information:
Options passed into column definitions.
const columns = table.createColumns([
  table.column({
    header: 'Name',
    accessor: 'name',
    plugins: {
      select: { ... },
    },
  }),
]);
const columns = table.createColumns([
  table.column({
    header: 'Name',
    accessor: 'name',
    plugins: {
      select: { ... },
    },
  }),
]);

Prop Set

Information:
Extensions to the view model. Read current.props on table components. The lists below are generated from the plugin's TypeScript prop-set type, so they match the published package exactly.

BodyRow props row.current.props.select

selected: boolean
Whether this row is selected.
someSubRowsSelected: boolean
Whether some (but not all) sub-rows are selected.
allSubRowsSelected: boolean
Whether all sub-rows are selected.

Interactions

  • allPageRowsSelected and somePageRowsSelected are scoped to the current page from addPagination, not the whole data set. Use allRowsSelected for the entire table.
  • The page-scoped values read the view model’s current.pageRows, which is computed on demand, so they work the same in a template, a test or headless code.
  • With addSubRows, selecting a parent selects its sub-rows, and someSubRowsSelected / allSubRowsSelected on the parent reflect the children’s state.

Plugin State

Information:
State provided by addSelectedRows.
const vm = table.createViewModel(columns)
const { pluginStates } = vm
const { selectedDataIds, allRowsSelected, getRowState } = pluginStates.select
const vm = table.createViewModel(columns)
const { pluginStates } = vm
const { selectedDataIds, allRowsSelected, getRowState } = pluginStates.select

selectedDataIds: RecordSet

The selected data ids (row.dataId). Read selectedDataIds.current (a Record<string, boolean> holding only true entries), or change it with add(id), remove(id), toggle(id), addAll(ids), removeAll(ids), clear() and has(id).

{Object.keys(selectedDataIds.current).length} row(s) selected.
<button onclick={() => selectedDataIds.clear()}>Clear selection</button>
{Object.keys(selectedDataIds.current).length} row(s) selected.
<button onclick={() => selectedDataIds.clear()}>Clear selection</button>

allRowsSelected: Box<boolean>

Whether every row is selected. Writing true selects every row; false clears the selection.

someRowsSelected: ReadonlyBox<boolean>

allPageRowsSelected: Box<boolean>

Whether every row on the current page is selected. Writing selects or deselects the page’s rows.

somePageRowsSelected: ReadonlyBox<boolean>

getRowState: (row) => SelectedRowsRowState

Returns the selection state of a BodyRow:

  • isSelected: Box<boolean>: writing selects or deselects the row (and, with linkDataSubRows, its sub-rows)
  • isSomeSubRowsSelected: ReadonlyBox<boolean>
  • isAllSubRowsSelected: ReadonlyBox<boolean>

The views hold no state of their own (they read selectedDataIds), so they never go stale; the same row object always returns the same views.

Information:
v7 removed invalidate(): there is no per-row cache to clear.

A checkbox takes the boxes as props:

<!-- SelectIndicator.svelte, rendered with createRender(SelectIndicator, getRowState(row)) -->
<script lang="ts">
    import type { Box, ReadonlyBox } from '@humanspeak/svelte-headless-table'
    const { isSelected, isSomeSubRowsSelected }: {
        isSelected: Box<boolean>
        isSomeSubRowsSelected: ReadonlyBox<boolean>
    } = $props()
</script>

<input
    type="checkbox"
    checked={isSelected.current}
    indeterminate={isSomeSubRowsSelected.current}
    onchange={(e) => (isSelected.current = e.currentTarget.checked)}
/>
<!-- SelectIndicator.svelte, rendered with createRender(SelectIndicator, getRowState(row)) -->
<script lang="ts">
    import type { Box, ReadonlyBox } from '@humanspeak/svelte-headless-table'
    const { isSelected, isSomeSubRowsSelected }: {
        isSelected: Box<boolean>
        isSomeSubRowsSelected: ReadonlyBox<boolean>
    } = $props()
</script>

<input
    type="checkbox"
    checked={isSelected.current}
    indeterminate={isSomeSubRowsSelected.current}
    onchange={(e) => (isSelected.current = e.currentTarget.checked)}
/>

Examples

Name (3 users)Info
First NameLast NameAgeStatusVisitsProfile Progress
RoyalAnderson38complicated4052
EliezerMcGlynn51single5183
RosieSawayn35relationship1725
{
  "selectedDataIds": {}
}