Row Selection
Useful Links
Actions
Table Demo
Select | Name | Age | Phone | |
---|---|---|---|---|
Kendra Weissnat-Ziemann | 41 | Lucious23@hotmail.com | (852) 838-0609 | |
Eleanor Hirthe | 28 | Dion38@gmail.com | (279) 388-6308 | |
Helen Nolan | 22 | Casimir.Stokes@gmail.com | (618) 580-1053 | |
Richard Bartell-Conn | 36 | Adolf51@gmail.com | (359) 280-6211 | |
Hubert Gorczany | 84 | Madaline27@hotmail.com | (444) 771-0168 | |
Clint Jenkins | 89 | Linnie22@hotmail.com | (796) 471-3480 | |
Mr. Melvin Leuschke-MacGyver | 66 | Ressie.Smith@yahoo.com | (383) 241-5706 | |
Eddie Dickens IV | 32 | Tad18@yahoo.com | (698) 637-5272 | |
Christian Conroy | 77 | Irwin.Lubowitz@gmail.com | (601) 550-2439 | |
Earnest West | 83 | Garrett_Crist@hotmail.com | (761) 925-7502 |
Debug
Selection State
{}
Explanation
In this guide, we'll focus on enhancing a table by adding a selection state that allows users to select rows using checkboxes. We'll go through the steps of creating a checkbox wrapper component, defining the columns with a selection column, setting up a reactive state for row selection, and ensuring that the table responds to selection changes.
You should already know how to make a basic table before proceeding.
🗒️ Note: This process works for all kinds of table state.
Creating the Checkbox Wrapper
We start by creating a simple checkbox wrapper component called TableCheckbox
.
This component will handle the checkbox rendering for each row in the table.
<!-- table-checkbox.svelte -->
<script lang="ts">
import type { HTMLInputAttributes } from 'svelte/elements';
type Props = {} & HTMLInputAttributes;
let { ...inputProps }: Props = $props();
</script>
<input type="checkbox" {...inputProps} />
Creating a Selection Column
Next, we define the table columns using a column helper, with a specific focus
on adding a selection column that uses the TableCheckbox
component.
<!-- +page.svelte -->
<script lang="ts">
import { createColumnHelper, renderComponent } from '$lib/table';
import TableCheckbox from './_components/table-checkbox.svelte';
import { type UserProfile } from '$lib/services/user-profile';
// Create a column helper for the user profile data.
const colHelp = createColumnHelper<UserProfile>();
// Define the columns including a column for row selection.
const columnDefs = [
// Add a column for selection
colHelp.display({
header: 'Select',
cell: ({ row }) =>
renderComponent(TableCheckbox, {
checked: row.getIsSelected(),
onchange: () => {
row.toggleSelected();
}
})
}),
colHelp.accessor('name', { header: 'Name' }),
colHelp.accessor('age', { header: 'Age' }),
colHelp.accessor('email', { header: 'Email' }),
colHelp.accessor('phone', { header: 'Phone' })
];
</script>
The checkbox's onchange
event toggles the selection of the respective row when
clicked.
Setting Up Selection State
To manage the row selection state reactively, we use a $state
rune to create a
reactive signal that tracks which rows are selected.
<script lang="ts">
import { createColumnHelper, renderComponent } from '$lib/table';
import { type RowSelectionState, createColumnHelper, renderComponent } from '$lib/table';
import TableCheckbox from './_components/table-checkbox.svelte';
import { type UserProfile } from '$lib/services/user-profile';
const colHelp = createColumnHelper<UserProfile>();
const columnDefs = [
colHelp.display({
header: 'Select',
cell: ({ row }) =>
renderComponent(TableCheckbox, {
checked: row.getIsSelected(),
onchange: () => {
row.toggleSelected();
}
})
}),
colHelp.accessor('name', { header: 'Name' }),
colHelp.accessor('age', { header: 'Age' }),
colHelp.accessor('email', { header: 'Email' }),
colHelp.accessor('phone', { header: 'Phone' })
];
// Define a reactive state to track the row selection state.
let rowSelectionState: RowSelectionState = $state({});
</script>
Creating the Updater Function
To handle changes in the row selection state, we define an updater function. This function will be called whenever a row's selection state changes.
<script lang="ts">
import { type RowSelectionState, createColumnHelper, renderComponent } from '$lib/table';
import {
type RowSelectionState,
type Updater,
createColumnHelper,
renderComponent
} from '$lib/table';
import TableCheckbox from './_components/table-checkbox.svelte';
import { type UserProfile } from '$lib/services/user-profile';
const colHelp = createColumnHelper<UserProfile>();
const columnDefs = [
colHelp.display({
header: 'Select',
cell: ({ row }) =>
renderComponent(TableCheckbox, {
checked: row.getIsSelected(),
onchange: () => {
row.toggleSelected();
}
})
}),
colHelp.accessor('name', { header: 'Name' }),
colHelp.accessor('age', { header: 'Age' }),
colHelp.accessor('email', { header: 'Email' }),
colHelp.accessor('phone', { header: 'Phone' })
];
let rowSelectionState: RowSelectionState = $state({});
function onRowSelectionChange(updater: Updater<RowSelectionState>) {
// Update the selection state by reassigning the $state
if (updater instanceof Function) {
rowSelectionState = updater(rowSelectionState);
} else {
rowSelectionState = updater;
}
}
</script>
- State Update: The updater function modifies the
rowSelectionState
, ensuring that the state rune and the table itself are synchronized. - Reactivity: Reassigning the
$state
triggers the reactive updates automatically.
Setting Up the Table
When setting up the table, it is essential to make the rowSelection
state a
getter to ensure reactivity. This way, the table automatically updates when the
selection state changes.
<script lang="ts">
import {
type RowSelectionState,
type Updater,
createColumnHelper,
renderComponent,
createSvelteTable,
getCoreRowModel
} from '$lib/table';
import TableCheckbox from './_components/table-checkbox.svelte';
import { type UserProfile } from '$lib/services/user-profile';
import { type UserProfile, userProfiles } from '$lib/services/user-profile';
const colHelp = createColumnHelper<UserProfile>();
const columnDefs = [
colHelp.display({
header: 'Select',
cell: ({ row }) =>
renderComponent(TableCheckbox, {
checked: row.getIsSelected(),
onchange: () => {
row.toggleSelected();
}
})
}),
colHelp.accessor('name', { header: 'Name' }),
colHelp.accessor('age', { header: 'Age' }),
colHelp.accessor('email', { header: 'Email' }),
colHelp.accessor('phone', { header: 'Phone' })
];
let rowSelectionState: RowSelectionState = $state({});
function onRowSelectionChange(updater: Updater<RowSelectionState>) {
if (updater instanceof Function) {
rowSelectionState = updater(rowSelectionState);
} else {
rowSelectionState = updater;
}
}
// Create the table and bind the row selection state using a getter.
const table = createSvelteTable({
data: userProfiles,
columns: columnDefs,
state: {
get rowSelection() {
return rowSelectionState;
}
},
onRowSelectionChange: onRowSelectionChange,
getCoreRowModel: getCoreRowModel()
});
</script>
Rendering the Table in the Markup
Finally, we render the table and include a button that allows users to toggle the selection of all rows at once.
<div>
<h2>Actions</h2>
<hr />
<button onclick={() => table.toggleAllRowsSelected()}>
{#if table.getIsAllRowsSelected()}
Deselect All
{:else}
Select All
{/if}
</button>
</div>
<table>
<thead>
<tr>
{#each table.getHeaderGroups() as headerGroup}
{#each headerGroup.headers as header}
<th>
<FlexRender content={header.column.columnDef.header} context={header.getContext()} />
</th>
{/each}
{/each}
</tr>
</thead>
<tbody>
{#each table.getRowModel().rows as row}
<tr>
{#each row.getVisibleCells() as cell}
<td>
<FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
</td>
{/each}
</tr>
{/each}
</tbody>
</table>