Skip to content

Commit c8742cd

Browse files
walker-txWalker Lockard
andauthored
docs: update svelte-table docs (#5622)
Co-authored-by: Walker Lockard <[email protected]>
1 parent 3b44168 commit c8742cd

File tree

2 files changed

+131
-104
lines changed

2 files changed

+131
-104
lines changed

docs/framework/svelte/guide/table-state.md

Lines changed: 57 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ TanStack Table has a simple underlying internal state management system to store
1010

1111
You do not need to set up anything special in order for the table state to work. If you pass nothing into either `state`, `initialState`, or any of the `on[State]Change` table options, the table will manage its own state internally. You can access any part of this internal state by using the `table.getState()` table instance API.
1212

13-
```jsx
14-
const options = writable({
13+
```ts
14+
const table = createTable({
1515
columns,
16-
data,
16+
get data() {
17+
return data
18+
},
1719
//...
1820
})
1921

20-
const table = createTable(options)
21-
2222
console.log(table.getState()) //access the entire internal state
2323
console.log(table.getState().rowSelection) //access just the row selection state
2424
```
@@ -27,8 +27,8 @@ console.log(table.getState().rowSelection) //access just the row selection state
2727

2828
If all you need to do for certain states is customize their initial default values, you still do not need to manage any of the state yourself. You can simply set values in the `initialState` option of the table instance.
2929

30-
```jsx
31-
const options = writable({
30+
```ts
31+
const table = createTable({
3232
columns,
3333
data,
3434
initialState: {
@@ -46,11 +46,9 @@ const options = writable({
4646
},
4747
//...
4848
})
49-
50-
const table = createTable(options)
5149
```
5250

53-
> **Note**: Only specify each particular state in either `initialState` or `state`, but not both. If you pass in a particular state value to both `initialState` and `state`, the initialized state in `state` will take overwrite any corresponding value in `initialState`.
51+
> **Note**: Only specify each particular state in either `initialState` or `state`, but not both. If you pass in a particular state value to both `initialState` and `state`, the initialized state in `state` will overwrite any corresponding value in `initialState`.
5452
5553
### Controlled State
5654

@@ -65,161 +63,129 @@ In order to control a particular state, you need to both pass in the correspondi
6563
Let's take filtering, sorting, and pagination as an example in a "manual" server-side data fetching scenario. You can store the filtering, sorting, and pagination state in your own state management, but leave out any other state like column order, column visibility, etc. if your API does not care about those values.
6664

6765
```ts
68-
let sorting = [
66+
let sorting: SortingState = $state([
6967
{
7068
id: 'age',
7169
desc: true, //sort by age in descending order by default
7270
},
73-
]
74-
const setSorting = updater => {
71+
])
72+
function setSorting(updater: Updater<SortingState>) {
7573
if (updater instanceof Function) {
7674
sorting = updater(sorting)
77-
} else {
78-
sorting = updater
79-
}
80-
options.update(old => ({
81-
...old,
82-
state: {
83-
...old.state,
84-
sorting,
85-
},
86-
}))
75+
} else sorting = updater
8776
}
8877

89-
let columnFilters = [] //no default filters
90-
const setColumnFilters = updater => {
78+
let columnFilters: ColumnFiltersState = $state([]) //no default filters
79+
function setColumnFilters(updater: Updater<ColumnFiltersState>) {
9180
if (updater instanceof Function) {
9281
columnFilters = updater(columnFilters)
93-
} else {
94-
columnFilters = updater
95-
}
96-
options.update(old => ({
97-
...old,
98-
state: {
99-
...old.state,
100-
columnFilters,
101-
},
102-
}))
82+
} else columnFilters = updater
10383
}
10484

105-
let pagination = { pageIndex: 0, pageSize: 15 } //default pagination
106-
const setPagination = updater => {
85+
let pagination: PaginationState = $state(
86+
{ pageIndex: 0, pageSize: 15 } //default pagination
87+
)
88+
function setPagination(updater: Updater<PaginationState>) {
10789
if (updater instanceof Function) {
10890
pagination = updater(pagination)
109-
} else {
110-
pagination = updater
111-
}
112-
options.update(old => ({
113-
...old,
114-
state: {
115-
...old.state,
116-
pagination,
117-
},
118-
}))
91+
} else pagination = updater
11992
}
12093

121-
//Use our controlled state values to fetch data
122-
const tableQuery = createQuery({
123-
queryKey: ['users', columnFilters, sorting, pagination],
124-
queryFn: () => fetchUsers(columnFilters, sorting, pagination),
125-
//...
126-
})
94+
let data = $state(makeData(100_000))
12795

128-
const options = writable({
96+
const options = {
12997
columns,
130-
data: tableQuery.data,
98+
get data() {
99+
return data
100+
}
131101
//...
132102
state: {
133-
columnFilters, //pass controlled state back to the table (overrides internal state)
134-
sorting,
135-
pagination
103+
get sorting() {
104+
return sorting
105+
},
106+
get columnFilters() {
107+
return columnFilters
108+
},
109+
get pagination() {
110+
return pagination
111+
}
136112
},
137113
onColumnFiltersChange: setColumnFilters, //hoist columnFilters state into our own state management
138114
onSortingChange: setSorting,
139115
onPaginationChange: setPagination,
140-
})
116+
}
141117

142118
const table = createTable(options)
143119
//...
144120
```
145121

146122
#### Fully Controlled State
147123

148-
Alternatively, you can control the entire table state with the `onStateChange` table option. It will hoist out the entire table state into your own state management system. Be careful with this approach, as you might find that raising some frequently changing state values up a svelte tree, like `columnSizingInfo` state`, might cause bad performance issues.
124+
Alternatively, you can control the entire table state with the `onStateChange` table option. It will hoist out the entire table state into your own state management system. Be careful with this approach, as you might find that raising some frequently changing state values up a Svelte tree, like `columnSizingInfo` state, might cause bad performance issues.
149125

150126
A couple of more tricks may be needed to make this work. If you use the `onStateChange` table option, the initial values of the `state` must be populated with all of the relevant state values for all of the features that you want to use. You can either manually type out all of the initial state values, or use the `table.setOptions` API in a special way as shown below.
151127

152-
```jsx
128+
```ts
153129
//create a table instance with default state values
154-
const options = writable({
130+
const table = createTable({
155131
columns,
156-
data,
132+
get data() {
133+
return data
134+
},
157135
//... Note: `state` values are NOT passed in yet
158136
})
159-
const table = createTable(options)
160137

161-
let state = {
138+
const state = $state({
162139
...table.initialState, //populate the initial state with all of the default state values from the table instance
163140
pagination: {
164141
pageIndex: 0,
165142
pageSize: 15 //optionally customize the initial pagination state.
166143
}
167-
}
144+
})
145+
168146
const setState = updater => {
169147
if (updater instanceof Function) {
170148
state = updater(state)
171-
} else {
172-
state = updater
173-
}
174-
options.update(old => ({
175-
...old,
176-
state,
177-
}))
149+
} state = updater
178150
}
179151

180152
//Use the table.setOptions API to merge our fully controlled state onto the table instance
181153
table.setOptions(prev => ({
182154
...prev, //preserve any other options that we have set up above
183-
state, //our fully controlled state overrides the internal state
155+
get state() {
156+
return state //our fully controlled state overrides the internal state
157+
},
184158
onStateChange: setState //any state changes will be pushed up to our own state management
185159
}))
186160
```
187161

188162
### On State Change Callbacks
189163

190-
So far, we have seen the `on[State]Change` and `onStateChange` table options work to "hoist" the table state changes into our own state management. However, there are a few things about these using these options that you should be aware of.
164+
So far, we have seen the `on[State]Change` and `onStateChange` table options work to "hoist" the table state changes into our own state management. However, there are a few things about using these options that you should be aware of.
191165

192166
#### 1. **State Change Callbacks MUST have their corresponding state value in the `state` option**.
193167

194168
Specifying an `on[State]Change` callback tells the table instance that this will be a controlled state. If you do not specify the corresponding `state` value, that state will be "frozen" with its initial value.
195169

196170
```ts
197-
let sorting = []
171+
let sorting = $state([])
198172
const setSorting = updater => {
199173
if (updater instanceof Function) {
200174
sorting = updater(sorting)
201-
} else {
202-
sorting = updater
203-
}
204-
options.update(old => ({
205-
...old,
206-
state: {
207-
...old.state,
208-
sorting,
209-
},
210-
}))
175+
} else sorting = updater
211176
}
212-
//...
213-
const options = writable({
177+
// ...
178+
const table = createTable({
214179
columns,
215180
data,
216181
//...
217182
state: {
218-
sorting, //required because we are using `onSortingChange`
183+
get sorting() {
184+
return sorting //required because we are using `onSortingChange`
185+
},
219186
},
220187
onSortingChange: setSorting, //makes the `state.sorting` controlled
221188
})
222-
const table = createTable(options)
223189
```
224190

225191
#### 2. **Updaters can either be raw values or callback functions**.
@@ -246,15 +212,6 @@ let sorting: SortingState[] = [
246212
const setSorting = (updater: Updater<SortingState>) => {
247213
if (updater instanceof Function) {
248214
sorting = updater(sorting)
249-
} else {
250-
sorting = updater
251-
}
252-
options.update(old => ({
253-
...old,
254-
state: {
255-
...old.state,
256-
sorting,
257-
},
258-
}))
215+
} else sorting = updater
259216
}
260217
```

docs/framework/svelte/svelte-table.md

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,88 @@
22
title: Svelte Table
33
---
44

5-
The `@tanstack/svelte-table` adapter is a wrapper around the core table logic. Most of it's job is related to managing state the "svelte" way, providing types and the rendering implementation of cell/header/footer templates.
5+
> **IMPORTANT:** This version of `@tanstack/svelte-table` only supports **Svelte 5 or
6+
> newer**. For Svelte 3/4 support, use version 8 of `@tanstack/svelte-table`.
67
7-
## `createTable`
8+
The `@tanstack/svelte-table` adapter is a wrapper around the core table logic. Most of its job is related to managing state the "Svelte" way, providing types and the rendering implementation of cell/header/footer templates.
9+
10+
## Exports
11+
12+
`@tanstack/svelte-table` re-exports all of `@tanstack/table-core`'s APIs and the following:
13+
14+
### `createTable`
815

916
Takes an `options` object and returns a table.
1017

1118
```svelte
1219
<script>
20+
import { createTable } from '@tanstack/svelte-table'
21+
22+
const table = createTable({
23+
/* ...table options... */
24+
})
25+
</script>
26+
27+
<!-- ...render your table in markup -->
28+
```
1329

14-
import { createTable } from '@tanstack/svelte-table'
30+
### FlexRender
1531

16-
const table = createTable(options)
32+
A Svelte component for rendering cell/header/footer templates with dynamic values.
1733

34+
FlexRender supports any type of renderable content supported by Svelte:
35+
- Scalar data types such as numbers, strings, etc.
36+
- Svelte components (when wrapped with `renderComponent`)
37+
38+
Example:
39+
40+
```svelte
41+
<script lang="ts">
42+
import {
43+
type ColumnDef,
44+
FlexRender,
45+
createTable,
46+
getCoreRowModel,
47+
renderComponent
48+
} from '@tanstack/svelte-table'
49+
import { StatusTag } from '$lib/components/status-tag.svelte'
50+
import type { Person } from './types'
51+
import { peopleData, type Person } from './people'
52+
53+
const columns: ColumnDef<Person>[] = [
54+
{
55+
/* Renders a string */
56+
accessorKey: 'name',
57+
cell: info => info.getValue(),
58+
},
59+
{
60+
/* Renders a Svelte component */
61+
accessorKey: 'status',
62+
cell: (info) => renderComponent(StatusTag, { value: info.getValue() })
63+
}
64+
]
65+
66+
const table = createTable({
67+
data: peopleData,
68+
columns,
69+
getCoreRowModel: getCoreRowModel()
70+
})
1871
</script>
72+
73+
<table>
74+
<tbody>
75+
{#each table.getRowModel().rows as row}
76+
<tr>
77+
{#each row.getVisibleCells() as cell}
78+
<td>
79+
<FlexRender
80+
content={cell.column.columnDef.cell}
81+
context={cell.getContext()}
82+
/>
83+
</td>
84+
{/each}
85+
</tr>
86+
{/each}
87+
</tbody>
88+
</table>
1989
```

0 commit comments

Comments
 (0)