@tanstack/table-core 9.0.0-beta.37 → 9.0.0-beta.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/core/headers/buildHeaderGroups.cjs.map +1 -1
- package/dist/core/headers/buildHeaderGroups.d.cts +1 -1
- package/dist/core/headers/buildHeaderGroups.d.ts +1 -1
- package/dist/core/headers/buildHeaderGroups.js.map +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.cjs +7 -7
- package/dist/core/headers/coreHeadersFeature.utils.cjs.map +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.js +7 -7
- package/dist/core/headers/coreHeadersFeature.utils.js.map +1 -1
- package/dist/core/table/coreTablesFeature.utils.cjs +1 -1
- package/dist/core/table/coreTablesFeature.utils.cjs.map +1 -1
- package/dist/core/table/coreTablesFeature.utils.js +1 -1
- package/dist/core/table/coreTablesFeature.utils.js.map +1 -1
- package/dist/features/column-ordering/columnOrderingFeature.types.d.cts +5 -5
- package/dist/features/column-ordering/columnOrderingFeature.types.d.ts +5 -5
- package/dist/features/column-ordering/columnOrderingFeature.utils.cjs +6 -6
- package/dist/features/column-ordering/columnOrderingFeature.utils.cjs.map +1 -1
- package/dist/features/column-ordering/columnOrderingFeature.utils.d.cts +3 -3
- package/dist/features/column-ordering/columnOrderingFeature.utils.d.ts +3 -3
- package/dist/features/column-ordering/columnOrderingFeature.utils.js +6 -6
- package/dist/features/column-ordering/columnOrderingFeature.utils.js.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.cjs +44 -39
- package/dist/features/column-pinning/columnPinningFeature.cjs.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.d.cts +6 -1
- package/dist/features/column-pinning/columnPinningFeature.d.ts +6 -1
- package/dist/features/column-pinning/columnPinningFeature.js +45 -40
- package/dist/features/column-pinning/columnPinningFeature.js.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.types.d.cts +49 -38
- package/dist/features/column-pinning/columnPinningFeature.types.d.ts +49 -38
- package/dist/features/column-pinning/columnPinningFeature.utils.cjs +154 -146
- package/dist/features/column-pinning/columnPinningFeature.utils.cjs.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.utils.d.cts +81 -73
- package/dist/features/column-pinning/columnPinningFeature.utils.d.ts +81 -73
- package/dist/features/column-pinning/columnPinningFeature.utils.js +141 -133
- package/dist/features/column-pinning/columnPinningFeature.utils.js.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.cjs +4 -4
- package/dist/features/column-sizing/columnSizingFeature.cjs.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.js +5 -5
- package/dist/features/column-sizing/columnSizingFeature.js.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.types.d.cts +18 -12
- package/dist/features/column-sizing/columnSizingFeature.types.d.ts +18 -12
- package/dist/features/column-sizing/columnSizingFeature.utils.cjs +24 -20
- package/dist/features/column-sizing/columnSizingFeature.utils.cjs.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.utils.d.cts +18 -14
- package/dist/features/column-sizing/columnSizingFeature.utils.d.ts +18 -14
- package/dist/features/column-sizing/columnSizingFeature.utils.js +24 -20
- package/dist/features/column-sizing/columnSizingFeature.utils.js.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs +16 -16
- package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.d.cts +3 -3
- package/dist/features/column-visibility/columnVisibilityFeature.utils.d.ts +3 -3
- package/dist/features/column-visibility/columnVisibilityFeature.utils.js +16 -16
- package/dist/features/column-visibility/columnVisibilityFeature.utils.js.map +1 -1
- package/dist/static-functions.cjs +16 -16
- package/dist/static-functions.d.cts +3 -3
- package/dist/static-functions.d.ts +3 -3
- package/dist/static-functions.js +3 -3
- package/package.json +1 -1
- package/skills/api-not-found/SKILL.md +113 -0
- package/skills/client-vs-server/SKILL.md +164 -0
- package/skills/column-faceting/SKILL.md +91 -0
- package/skills/column-filtering/SKILL.md +82 -0
- package/skills/column-ordering/SKILL.md +75 -0
- package/skills/column-pinning/SKILL.md +89 -0
- package/skills/column-resizing/SKILL.md +91 -0
- package/skills/column-sizing/SKILL.md +72 -0
- package/skills/column-visibility/SKILL.md +75 -0
- package/skills/core/SKILL.md +140 -0
- package/skills/custom-features/SKILL.md +207 -0
- package/skills/expanding/SKILL.md +80 -0
- package/skills/global-filtering/SKILL.md +84 -0
- package/skills/grouping/SKILL.md +50 -394
- package/skills/migrate-v8-to-v9/SKILL.md +230 -390
- package/skills/pagination/SKILL.md +35 -344
- package/skills/row-pinning/SKILL.md +47 -238
- package/skills/row-selection/SKILL.md +39 -351
- package/skills/sorting/SKILL.md +35 -299
- package/skills/table-features/SKILL.md +153 -0
- package/skills/typescript/SKILL.md +126 -0
- package/src/core/headers/buildHeaderGroups.ts +1 -1
- package/src/core/headers/coreHeadersFeature.utils.ts +7 -7
- package/src/core/table/coreTablesFeature.utils.ts +1 -1
- package/src/features/column-ordering/columnOrderingFeature.types.ts +5 -5
- package/src/features/column-ordering/columnOrderingFeature.utils.ts +9 -9
- package/src/features/column-pinning/columnPinningFeature.ts +64 -59
- package/src/features/column-pinning/columnPinningFeature.types.ts +49 -38
- package/src/features/column-pinning/columnPinningFeature.utils.ts +163 -155
- package/src/features/column-sizing/columnSizingFeature.ts +6 -6
- package/src/features/column-sizing/columnSizingFeature.types.ts +18 -12
- package/src/features/column-sizing/columnSizingFeature.utils.ts +31 -27
- package/src/features/column-visibility/columnVisibilityFeature.utils.ts +15 -15
- package/skills/column-definitions/SKILL.md +0 -330
- package/skills/column-layout/SKILL.md +0 -326
- package/skills/column-layout/references/subsystems.md +0 -220
- package/skills/customizing-feature-behavior/SKILL.md +0 -423
- package/skills/filtering/SKILL.md +0 -375
- package/skills/filtering/references/faceting-and-fuzzy.md +0 -218
- package/skills/row-expanding/SKILL.md +0 -356
- package/skills/setup/SKILL.md +0 -390
- package/skills/state-management/SKILL.md +0 -403
|
@@ -1,388 +1,76 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: row-selection
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
`enableMultiRowSelection: false` for radio-style, `enableSubRowSelection`,
|
|
13
|
-
and why `getRowId` is essentially mandatory — especially under server pagination.
|
|
14
|
-
type: core
|
|
15
|
-
library: tanstack-table
|
|
16
|
-
library_version: '9.0.0-alpha.48'
|
|
17
|
-
requires:
|
|
18
|
-
- state-management
|
|
19
|
-
- column-definitions
|
|
4
|
+
Maintain rowSelection ID state with stable getRowId, single, multi, and subrow rules, selected row models, and manual-pagination semantics. Load when selected IDs outlive loaded Row objects or data removal.
|
|
5
|
+
metadata:
|
|
6
|
+
{
|
|
7
|
+
type: sub-skill,
|
|
8
|
+
library: '@tanstack/table-core',
|
|
9
|
+
library_version: '9.0.0-beta.42',
|
|
10
|
+
}
|
|
11
|
+
requires: ['core', 'table-features']
|
|
20
12
|
sources:
|
|
21
|
-
- TanStack/table:docs/guide/row-selection.md
|
|
22
|
-
- TanStack/table:packages/table-core/src/features/row-selection
|
|
23
|
-
- TanStack/table:
|
|
24
|
-
- TanStack/table:examples/react/row-selection/src/main.tsx
|
|
13
|
+
- 'TanStack/table:docs/framework/react/guide/row-selection.md'
|
|
14
|
+
- 'TanStack/table:packages/table-core/src/features/row-selection'
|
|
15
|
+
- 'TanStack/table:examples/react/row-selection'
|
|
25
16
|
---
|
|
26
17
|
|
|
27
|
-
This skill builds on `
|
|
18
|
+
This skill builds on `core` and `table-features`. Selection is independent ID state; selected row models can only materialize loaded rows.
|
|
28
19
|
|
|
29
20
|
## Setup
|
|
30
21
|
|
|
31
22
|
```ts
|
|
32
|
-
import {
|
|
33
|
-
tableFeatures,
|
|
34
|
-
rowSelectionFeature,
|
|
35
|
-
constructTable,
|
|
36
|
-
} from '@tanstack/table-core'
|
|
37
|
-
import type { RowSelectionState } from '@tanstack/table-core'
|
|
23
|
+
import { rowSelectionFeature, tableFeatures } from '@tanstack/table-core'
|
|
38
24
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
getRowId: (row) => row.id, // ← essentially mandatory
|
|
46
|
-
initialState: { rowSelection: {} satisfies RowSelectionState },
|
|
47
|
-
enableRowSelection: true,
|
|
48
|
-
})
|
|
25
|
+
type Person = { id: string; name: string }
|
|
26
|
+
export const features = tableFeatures({ rowSelectionFeature })
|
|
27
|
+
export const options = {
|
|
28
|
+
getRowId: (row: Person) => row.id,
|
|
29
|
+
enableSubRowSelection: false,
|
|
30
|
+
}
|
|
49
31
|
```
|
|
50
32
|
|
|
51
33
|
## Core Patterns
|
|
52
34
|
|
|
53
|
-
### Select column with header "select all" + per-row checkbox
|
|
54
|
-
|
|
55
|
-
```tsx
|
|
56
|
-
// From examples/react/row-selection/src/main.tsx
|
|
57
|
-
columnHelper.display({
|
|
58
|
-
id: 'select',
|
|
59
|
-
header: ({ table }) => (
|
|
60
|
-
<Checkbox
|
|
61
|
-
checked={table.getIsAllRowsSelected()}
|
|
62
|
-
indeterminate={table.getIsSomeRowsSelected()}
|
|
63
|
-
onChange={table.getToggleAllRowsSelectedHandler()}
|
|
64
|
-
/>
|
|
65
|
-
),
|
|
66
|
-
cell: ({ row }) => (
|
|
67
|
-
<Checkbox
|
|
68
|
-
checked={row.getIsSelected()}
|
|
69
|
-
indeterminate={row.getIsSomeSelected()}
|
|
70
|
-
disabled={!row.getCanSelect()}
|
|
71
|
-
onChange={row.getToggleSelectedHandler()}
|
|
72
|
-
/>
|
|
73
|
-
),
|
|
74
|
-
}),
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Single-select (radio-style)
|
|
78
|
-
|
|
79
|
-
```tsx
|
|
80
|
-
const table = useTable({
|
|
81
|
-
features: tableFeatures({ rowSelectionFeature }),
|
|
82
|
-
columns,
|
|
83
|
-
data,
|
|
84
|
-
getRowId: (row) => row.id,
|
|
85
|
-
enableMultiRowSelection: false, // ← radio-like
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// Cell renders a radio, no "select all" header makes sense
|
|
89
|
-
columnHelper.display({
|
|
90
|
-
id: 'select',
|
|
91
|
-
header: '', // no select-all in single-select mode
|
|
92
|
-
cell: ({ row }) => (
|
|
93
|
-
<input
|
|
94
|
-
type="radio"
|
|
95
|
-
name="row-selection"
|
|
96
|
-
checked={row.getIsSelected()}
|
|
97
|
-
disabled={!row.getCanSelect()}
|
|
98
|
-
onChange={row.getToggleSelectedHandler()}
|
|
99
|
-
/>
|
|
100
|
-
),
|
|
101
|
-
})
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Conditional selection per row
|
|
105
|
-
|
|
106
35
|
```ts
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
columns,
|
|
110
|
-
data,
|
|
111
|
-
getRowId: (row) => row.id,
|
|
112
|
-
enableRowSelection: (row) => row.original.age > 18, // predicate form
|
|
113
|
-
})
|
|
36
|
+
const selectedIds = table.getSelectedRowIds()
|
|
37
|
+
const loadedSelectedRows = table.getSelectedRowModel().rows
|
|
114
38
|
```
|
|
115
39
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
```ts
|
|
119
|
-
table.getSelectedRowModel() // built off core — raw data
|
|
120
|
-
table.getFilteredSelectedRowModel() // built off filtered — current filters applied
|
|
121
|
-
table.getGroupedSelectedRowModel() // built off grouped — current groups applied
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Hoist selection to an external atom
|
|
125
|
-
|
|
126
|
-
```tsx
|
|
127
|
-
import { useCreateAtom } from '@tanstack/react-store'
|
|
128
|
-
|
|
129
|
-
const rowSelectionAtom = useCreateAtom<RowSelectionState>({})
|
|
130
|
-
|
|
131
|
-
const table = useTable({
|
|
132
|
-
features,
|
|
133
|
-
columns,
|
|
134
|
-
data,
|
|
135
|
-
getRowId: (row) => row.id,
|
|
136
|
-
atoms: { rowSelection: rowSelectionAtom },
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
// Send selected IDs to an API call from a sibling component
|
|
140
|
-
function ExportButton() {
|
|
141
|
-
const selection = useStore(rowSelectionAtom)
|
|
142
|
-
return (
|
|
143
|
-
<button onClick={() => api.export(Object.keys(selection))}>Export</button>
|
|
144
|
-
)
|
|
145
|
-
}
|
|
146
|
-
```
|
|
40
|
+
Use IDs for database-wide intent and row models for currently loaded objects.
|
|
147
41
|
|
|
148
42
|
## Common Mistakes
|
|
149
43
|
|
|
150
|
-
### [HIGH]
|
|
44
|
+
### [HIGH] Expecting selection to clean itself
|
|
151
45
|
|
|
152
|
-
Wrong:
|
|
46
|
+
Wrong: `data = data.filter(row => row.id !== deletedId)`
|
|
153
47
|
|
|
154
|
-
|
|
155
|
-
// Server-side pagination + default row.id = row.index
|
|
156
|
-
const table = useTable({
|
|
157
|
-
features: tableFeatures({ rowSelectionFeature, rowPaginationFeature }),
|
|
158
|
-
data, // only current page from server
|
|
159
|
-
manualPagination: true,
|
|
160
|
-
rowCount,
|
|
161
|
-
})
|
|
162
|
-
// After paging, rowSelection: { '5': true } is ambiguous
|
|
163
|
-
// — selection appears to move with the user.
|
|
164
|
-
```
|
|
48
|
+
Correct: `data = data.filter(row => row.id !== deletedId); table.setRowSelection(old => { const next = { ...old }; delete next[deletedId]; return next })`
|
|
165
49
|
|
|
166
|
-
|
|
50
|
+
Selection is independent state and can retain IDs after data removal.
|
|
167
51
|
|
|
168
|
-
|
|
169
|
-
const table = useTable({
|
|
170
|
-
features: tableFeatures({ rowSelectionFeature, rowPaginationFeature }),
|
|
171
|
-
data,
|
|
172
|
-
manualPagination: true,
|
|
173
|
-
rowCount,
|
|
174
|
-
getRowId: (row) => row.uuid, // stable across pages
|
|
175
|
-
})
|
|
52
|
+
Source: `https://github.com/TanStack/table/issues/5850`
|
|
176
53
|
|
|
177
|
-
|
|
178
|
-
const totalSelected = Object.keys(table.state.rowSelection).length
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
`row.id` defaults to `row.index`. Under `manualPagination`, every page reuses indices 0..n-1, so selection IDs collide across pages.
|
|
182
|
-
|
|
183
|
-
Source: docs/guide/row-selection.md; examples/react/row-selection/src/main.tsx
|
|
184
|
-
|
|
185
|
-
### [MEDIUM] `enableMultiRowSelection: false` + a "select all" checkbox header
|
|
186
|
-
|
|
187
|
-
Wrong:
|
|
188
|
-
|
|
189
|
-
```tsx
|
|
190
|
-
const table = useTable({
|
|
191
|
-
features: tableFeatures({ rowSelectionFeature }),
|
|
192
|
-
enableMultiRowSelection: false, // radio-like
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
// Header still renders a checkbox + indeterminate
|
|
196
|
-
<Checkbox
|
|
197
|
-
checked={table.getIsAllRowsSelected()}
|
|
198
|
-
indeterminate={table.getIsSomeRowsSelected()}
|
|
199
|
-
onChange={table.getToggleAllRowsSelectedHandler()}
|
|
200
|
-
/>
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Correct:
|
|
204
|
-
|
|
205
|
-
```tsx
|
|
206
|
-
const table = useTable({
|
|
207
|
-
features: tableFeatures({ rowSelectionFeature }),
|
|
208
|
-
enableMultiRowSelection: false,
|
|
209
|
-
getRowId: (row) => row.id,
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
// Drop the toggle-all header in single-select mode
|
|
213
|
-
columnHelper.display({
|
|
214
|
-
id: 'select',
|
|
215
|
-
header: '',
|
|
216
|
-
cell: ({ row }) => (
|
|
217
|
-
<input
|
|
218
|
-
type="radio"
|
|
219
|
-
name="row-selection"
|
|
220
|
-
checked={row.getIsSelected()}
|
|
221
|
-
disabled={!row.getCanSelect()}
|
|
222
|
-
onChange={row.getToggleSelectedHandler()}
|
|
223
|
-
/>
|
|
224
|
-
),
|
|
225
|
-
})
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
In single-select mode, `mutateRowIsSelected` clears all other ids before adding the new one. "Select all" becomes effectively no-op and indeterminate is meaningless.
|
|
229
|
-
|
|
230
|
-
Source: docs/guide/row-selection.md; packages/table-core/src/features/row-selection/rowSelectionFeature.utils.ts
|
|
54
|
+
### [HIGH] Selecting mutable indexes
|
|
231
55
|
|
|
232
|
-
|
|
56
|
+
Wrong: `const options = { getRowId: (_row: Person, index: number) => String(index) }`
|
|
233
57
|
|
|
234
|
-
|
|
58
|
+
Correct: `const options = { getRowId: (row: Person) => row.id }`
|
|
235
59
|
|
|
236
|
-
|
|
237
|
-
// Under manualPagination, only counts the visible page's selected rows
|
|
238
|
-
const selectedCount = table.getSelectedRowModel().flatRows.length
|
|
60
|
+
Stable application IDs preserve identity as row order and pages change.
|
|
239
61
|
|
|
240
|
-
|
|
241
|
-
const ids = table.getSelectedRowModel().flatRows.map((row) => row.original.id)
|
|
242
|
-
api.archive(ids) // missing all selections from other pages!
|
|
243
|
-
}
|
|
244
|
-
```
|
|
62
|
+
Source: `docs/framework/react/guide/row-selection.md#useful-row-ids`
|
|
245
63
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
```ts
|
|
249
|
-
// For counts and id lists under manualPagination, read state directly
|
|
250
|
-
const selectedCount = Object.keys(table.state.rowSelection).length
|
|
251
|
-
|
|
252
|
-
const handleBulkAction = () => {
|
|
253
|
-
const ids = Object.keys(table.state.rowSelection)
|
|
254
|
-
api.archive(ids)
|
|
255
|
-
}
|
|
256
|
-
// (Client-side: getSelectedRowModel is fine — data contains every row.)
|
|
257
|
-
```
|
|
64
|
+
### [HIGH] Treating loaded model as global selection
|
|
258
65
|
|
|
259
|
-
|
|
66
|
+
Wrong: `const allSelectedRecords = table.getSelectedRowModel().rows`
|
|
260
67
|
|
|
261
|
-
|
|
68
|
+
Correct: `const allSelectedIds = table.getSelectedRowIds()`
|
|
262
69
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
Wrong:
|
|
266
|
-
|
|
267
|
-
```ts
|
|
268
|
-
// Default behavior: clicking the parent selects all children
|
|
269
|
-
const table = useTable({
|
|
270
|
-
features: tableFeatures({ rowSelectionFeature, rowExpandingFeature }),
|
|
271
|
-
getSubRows: (row) => row.subRows,
|
|
272
|
-
// enableSubRowSelection unset — defaults to true
|
|
273
|
-
})
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
Correct:
|
|
277
|
-
|
|
278
|
-
```ts
|
|
279
|
-
const table = useTable({
|
|
280
|
-
features: tableFeatures({ rowSelectionFeature, rowExpandingFeature }),
|
|
281
|
-
getSubRows: (row) => row.subRows,
|
|
282
|
-
enableSubRowSelection: false, // toggling parent doesn't touch subRows
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
// Or selectively:
|
|
286
|
-
enableSubRowSelection: (row) => row.depth > 0,
|
|
287
|
-
|
|
288
|
-
// Indeterminate parent checkbox
|
|
289
|
-
<Checkbox
|
|
290
|
-
checked={row.getIsSelected()}
|
|
291
|
-
indeterminate={row.getIsSomeSelected()} // 'some' descendants selected
|
|
292
|
-
disabled={!row.getCanSelect()}
|
|
293
|
-
onChange={row.getToggleSelectedHandler()}
|
|
294
|
-
/>
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
`enableSubRowSelection: true` is the default. `mutateRowIsSelected` recurses into `row.subRows` when truthy. Decide deliberately — "select group as a whole" UX wants this off.
|
|
298
|
-
|
|
299
|
-
Source: docs/guide/row-selection.md; packages/table-core/src/features/row-selection/rowSelectionFeature.utils.ts
|
|
300
|
-
|
|
301
|
-
### [HIGH] Parent checkbox stuck "unchecked" with all sub-rows selected (deep trees)
|
|
302
|
-
|
|
303
|
-
Wrong:
|
|
304
|
-
|
|
305
|
-
```ts
|
|
306
|
-
// Returns false even when all leaf descendants are selected
|
|
307
|
-
const isParentChecked = row.getIsAllSubRowsSelected()
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Correct:
|
|
311
|
-
|
|
312
|
-
```ts
|
|
313
|
-
const allLeafs = row.getLeafRows()
|
|
314
|
-
const allSelected =
|
|
315
|
-
allLeafs.length > 0 && allLeafs.every((r) => r.getIsSelected())
|
|
316
|
-
const someSelected = allLeafs.some((r) => r.getIsSelected())
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
`getIsAllSubRowsSelected` only counts direct children. With multi-level grouping, a parent reports based on a partial count.
|
|
320
|
-
|
|
321
|
-
Source: https://github.com/TanStack/table/issues/4878; https://github.com/TanStack/table/issues/4759
|
|
322
|
-
|
|
323
|
-
### [HIGH] Stale rowSelection IDs after data refresh
|
|
324
|
-
|
|
325
|
-
Wrong:
|
|
326
|
-
|
|
327
|
-
```ts
|
|
328
|
-
useEffect(() => {
|
|
329
|
-
refreshData() // selection still references deleted IDs
|
|
330
|
-
}, [trigger])
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
Correct:
|
|
334
|
-
|
|
335
|
-
```ts
|
|
336
|
-
useEffect(() => {
|
|
337
|
-
setRowSelection((prev) => {
|
|
338
|
-
const validIds = new Set(data.map((row) => row.id))
|
|
339
|
-
const next: RowSelectionState = {}
|
|
340
|
-
for (const id in prev) if (validIds.has(id)) next[id] = prev[id]
|
|
341
|
-
return next
|
|
342
|
-
})
|
|
343
|
-
}, [data])
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
v8 removed v7's `autoResetSelectedRows`. With websockets / refetch, IDs that no longer exist remain in `rowSelection` and `getIsAllRowsSelected()` returns true based on stale state. Prune yourself.
|
|
347
|
-
|
|
348
|
-
Source: https://github.com/TanStack/table/issues/5850; https://github.com/TanStack/table/issues/4498
|
|
349
|
-
|
|
350
|
-
### [CRITICAL] Reimplementing selection state manually
|
|
351
|
-
|
|
352
|
-
Wrong:
|
|
353
|
-
|
|
354
|
-
```ts
|
|
355
|
-
// Hand-rolled "selected" set, bypassing the table
|
|
356
|
-
const [selected, setSelected] = useState(new Set<string>())
|
|
357
|
-
const toggle = (id: string) => {
|
|
358
|
-
setSelected((s) => {
|
|
359
|
-
const next = new Set(s)
|
|
360
|
-
next.has(id) ? next.delete(id) : next.add(id)
|
|
361
|
-
return next
|
|
362
|
-
})
|
|
363
|
-
}
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
Correct:
|
|
367
|
-
|
|
368
|
-
```ts
|
|
369
|
-
const table = useTable({
|
|
370
|
-
features: tableFeatures({ rowSelectionFeature }),
|
|
371
|
-
columns,
|
|
372
|
-
data,
|
|
373
|
-
getRowId: (row) => row.id,
|
|
374
|
-
})
|
|
375
|
-
row.toggleSelected()
|
|
376
|
-
row.toggleSelected(true)
|
|
377
|
-
table.toggleAllRowsSelected()
|
|
378
|
-
table.setRowSelection({ abc: true })
|
|
379
|
-
```
|
|
70
|
+
Under manual pagination, unloaded selected IDs have no `Row` object in the current model.
|
|
380
71
|
|
|
381
|
-
Source:
|
|
72
|
+
Source: `docs/framework/react/guide/row-selection.md#note-if-you-are-using-manualpagination`
|
|
382
73
|
|
|
383
|
-
##
|
|
74
|
+
## API Discovery
|
|
384
75
|
|
|
385
|
-
|
|
386
|
-
- `tanstack-table/state-management` — `rowSelection` slice + atoms for sharing selection
|
|
387
|
-
- `tanstack-table/pagination` — server-pagination "select all" pitfalls
|
|
388
|
-
- `tanstack-table/grouping` — `getGroupedSelectedRowModel` distinction
|
|
76
|
+
Inspect `node_modules/@tanstack/table-core/src/features/row-selection/` for state, row-model variants, and selection enablement callbacks.
|