@tanstack/angular-table 9.0.0-alpha.47 → 9.0.0-alpha.49
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 +10 -0
- package/dist/README.md +10 -0
- package/dist/fesm2022/tanstack-angular-table.mjs +18 -18
- package/package.json +8 -6
- package/skills/angular/angular-rendering-directives/SKILL.md +415 -0
- package/skills/angular/angular-rendering-directives/references/content-shapes.md +142 -0
- package/skills/angular/angular-rendering-directives/references/create-table-hook-registries.md +89 -0
- package/skills/angular/angular-rendering-directives/references/di-tokens.md +171 -0
- package/skills/angular/angular-rendering-directives/references/flex-render-component-options.md +64 -0
- package/skills/angular/client-to-server/SKILL.md +467 -0
- package/skills/angular/compose-with-tanstack-query/SKILL.md +482 -0
- package/skills/angular/compose-with-tanstack-store/SKILL.md +396 -0
- package/skills/angular/compose-with-tanstack-virtual/SKILL.md +400 -0
- package/skills/angular/getting-started/SKILL.md +496 -0
- package/skills/angular/getting-started/references/feature-row-model-mapping.md +48 -0
- package/skills/angular/migrate-v8-to-v9/SKILL.md +415 -0
- package/skills/angular/migrate-v8-to-v9/references/v8-to-v9-mapping.md +261 -0
- package/skills/angular/production-readiness/SKILL.md +468 -0
- package/skills/angular/table-state/SKILL.md +425 -0
- package/skills/angular/table-state/references/external-atoms-and-app-hook.md +152 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: angular/migrate-v8-to-v9
|
|
3
|
+
description: >
|
|
4
|
+
Mechanical v8 → v9 migration for `@tanstack/angular-table`: `createAngularTable` →
|
|
5
|
+
`injectTable`, `get*RowModel()` options → `_rowModels` factories with explicit `*Fns`,
|
|
6
|
+
required `_features` via `tableFeatures()`, `state` access via `table.store.state` instead
|
|
7
|
+
of `table.getState()`, `createColumnHelper<TFeatures, TData>()` generic-order flip, every
|
|
8
|
+
type now requires `TFeatures`, `enablePinning` split into `enableColumnPinning` /
|
|
9
|
+
`enableRowPinning`, `sortingFn` → `sortFn` rename pile, `ColumnSizingInfo` → `ColumnResizing`
|
|
10
|
+
split, removal of `_`-prefixed internals, signal-backed atoms replacing v8 memoized accessors,
|
|
11
|
+
and structural-directive rendering replacing v8 component-based rendering.
|
|
12
|
+
type: lifecycle
|
|
13
|
+
library: tanstack-table
|
|
14
|
+
framework: angular
|
|
15
|
+
library_version: '9.0.0-alpha.48'
|
|
16
|
+
requires:
|
|
17
|
+
- angular/table-state
|
|
18
|
+
- angular/getting-started
|
|
19
|
+
- angular/angular-rendering-directives
|
|
20
|
+
sources:
|
|
21
|
+
- TanStack/table:docs/framework/angular/guide/migrating.md
|
|
22
|
+
- TanStack/table:docs/framework/angular/angular-table.md
|
|
23
|
+
- TanStack/table:packages/angular-table/src/injectTable.ts
|
|
24
|
+
- TanStack/table:packages/angular-table/src/reactivity.ts
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Migrate from TanStack Table v8 to v9 (Angular)
|
|
28
|
+
|
|
29
|
+
> **Angular does not ship a legacy v8 API in v9** (unlike React's
|
|
30
|
+
> `useLegacyTable`). You migrate directly to v9's `injectTable` + `_features` +
|
|
31
|
+
> `_rowModels` shape. There is no incremental in-place adapter — the public
|
|
32
|
+
> entrypoint name itself changes.
|
|
33
|
+
|
|
34
|
+
This skill is a mechanical translation table. Work through it top-to-bottom.
|
|
35
|
+
|
|
36
|
+
For exhaustive lookup tables (row-model mapping, feature registration, type
|
|
37
|
+
generics, sorting renames, sizing-vs-resizing split, etc.) →
|
|
38
|
+
[`references/v8-to-v9-mapping.md`](references/v8-to-v9-mapping.md).
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 1. Entrypoint rename
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// v8
|
|
46
|
+
import { createAngularTable, getCoreRowModel } from '@tanstack/angular-table'
|
|
47
|
+
|
|
48
|
+
const v8Table = createAngularTable(() => ({
|
|
49
|
+
columns,
|
|
50
|
+
data: data(),
|
|
51
|
+
getCoreRowModel: getCoreRowModel(),
|
|
52
|
+
}))
|
|
53
|
+
|
|
54
|
+
// v9
|
|
55
|
+
import { injectTable, tableFeatures } from '@tanstack/angular-table'
|
|
56
|
+
|
|
57
|
+
const _features = tableFeatures({}) // empty is valid; core row model is automatic
|
|
58
|
+
|
|
59
|
+
const v9Table = injectTable(() => ({
|
|
60
|
+
_features,
|
|
61
|
+
_rowModels: {},
|
|
62
|
+
columns,
|
|
63
|
+
data: data(),
|
|
64
|
+
}))
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Key behavioral change: **the `injectTable` initializer re-runs when signals
|
|
68
|
+
inside it change**, then the adapter calls `table.setOptions({ ...prev, ...new })`.
|
|
69
|
+
Move stable values (`columns`, `_features`, `_rowModels`) **outside** the
|
|
70
|
+
initializer so they aren't recreated on every data update.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. Required new options: `_features` + `_rowModels`
|
|
75
|
+
|
|
76
|
+
v9 is opt-in for every feature. **Both options are required.**
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// v8 — features were bundled, row models added piecewise
|
|
80
|
+
createAngularTable(() => ({
|
|
81
|
+
columns,
|
|
82
|
+
data: data(),
|
|
83
|
+
getCoreRowModel: getCoreRowModel(),
|
|
84
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
85
|
+
getSortedRowModel: getSortedRowModel(),
|
|
86
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
87
|
+
filterFns, // root option
|
|
88
|
+
sortingFns, // root option
|
|
89
|
+
}))
|
|
90
|
+
|
|
91
|
+
// v9
|
|
92
|
+
import {
|
|
93
|
+
injectTable,
|
|
94
|
+
tableFeatures,
|
|
95
|
+
columnFilteringFeature,
|
|
96
|
+
rowSortingFeature,
|
|
97
|
+
rowPaginationFeature,
|
|
98
|
+
createFilteredRowModel,
|
|
99
|
+
createSortedRowModel,
|
|
100
|
+
createPaginatedRowModel,
|
|
101
|
+
filterFns,
|
|
102
|
+
sortFns, // note rename: sortingFns → sortFns
|
|
103
|
+
} from '@tanstack/angular-table'
|
|
104
|
+
|
|
105
|
+
const _features = tableFeatures({
|
|
106
|
+
columnFilteringFeature,
|
|
107
|
+
rowSortingFeature,
|
|
108
|
+
rowPaginationFeature,
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
injectTable(() => ({
|
|
112
|
+
_features,
|
|
113
|
+
_rowModels: {
|
|
114
|
+
filteredRowModel: createFilteredRowModel(filterFns), // fns are PARAMETERS now
|
|
115
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
116
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
117
|
+
},
|
|
118
|
+
columns,
|
|
119
|
+
data: data(),
|
|
120
|
+
}))
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Row-model and feature lookup tables → [`references/v8-to-v9-mapping.md`](references/v8-to-v9-mapping.md#row-model-migration-table).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 3. State access: `getState()` → `table.store.state` (and atoms)
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
// v8
|
|
131
|
+
const { sorting, pagination } = table.getState()
|
|
132
|
+
|
|
133
|
+
// v9 — flat snapshot
|
|
134
|
+
const { sorting, pagination } = table.store.state
|
|
135
|
+
|
|
136
|
+
// v9 — per slice (signal-backed in Angular)
|
|
137
|
+
const sorting = table.atoms.sorting.get()
|
|
138
|
+
const pagination = table.atoms.pagination.get()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
In Angular, all three (`table.atoms.<slice>`, `table.store.state`,
|
|
142
|
+
`table.baseAtoms.<slice>`) are signal-backed — reading them inside a template,
|
|
143
|
+
`computed(...)`, or `effect(...)` registers an Angular dependency
|
|
144
|
+
automatically. No `toSignal(...)` wrappers needed.
|
|
145
|
+
|
|
146
|
+
See `tanstack-table/angular/table-state` for the full state surface mental
|
|
147
|
+
model.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 4. Controlled state — `on[State]Change` shape
|
|
152
|
+
|
|
153
|
+
The shape is largely the same. **`onStateChange` (the single global v8 hook) is
|
|
154
|
+
gone in v9.** Slices are controlled individually via `state.<slice>` +
|
|
155
|
+
`on[State]Change` callbacks. Each callback receives either a new value or an
|
|
156
|
+
updater function:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// v9 pattern
|
|
160
|
+
import { signal } from '@angular/core'
|
|
161
|
+
import type { SortingState, PaginationState } from '@tanstack/angular-table'
|
|
162
|
+
|
|
163
|
+
readonly sorting = signal<SortingState>([])
|
|
164
|
+
readonly pagination = signal<PaginationState>({ pageIndex: 0, pageSize: 10 })
|
|
165
|
+
|
|
166
|
+
readonly table = injectTable(() => ({
|
|
167
|
+
_features,
|
|
168
|
+
_rowModels: { /* … */ },
|
|
169
|
+
columns,
|
|
170
|
+
data: this.data(),
|
|
171
|
+
state: {
|
|
172
|
+
sorting: this.sorting(),
|
|
173
|
+
pagination: this.pagination(),
|
|
174
|
+
},
|
|
175
|
+
onSortingChange: (updater) => {
|
|
176
|
+
updater instanceof Function
|
|
177
|
+
? this.sorting.update(updater)
|
|
178
|
+
: this.sorting.set(updater)
|
|
179
|
+
},
|
|
180
|
+
onPaginationChange: (updater) => {
|
|
181
|
+
updater instanceof Function
|
|
182
|
+
? this.pagination.update(updater)
|
|
183
|
+
: this.pagination.set(updater)
|
|
184
|
+
},
|
|
185
|
+
}))
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
> Always check `updater instanceof Function` (or `typeof updater === 'function'`).
|
|
189
|
+
> TanStack Table calls the callback with both shapes depending on the
|
|
190
|
+
> transition.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 5. Column helper generic-order flip
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
// v8
|
|
198
|
+
const columnHelper = createColumnHelper<Person>()
|
|
199
|
+
|
|
200
|
+
// v9 — TFeatures FIRST, then TData
|
|
201
|
+
const columnHelper = createColumnHelper<typeof _features, Person>()
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
New in v9: `columnHelper.columns([...])` preserves each column's `TValue` —
|
|
205
|
+
prefer it over a bare array literal:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const columns = columnHelper.columns([
|
|
209
|
+
columnHelper.accessor('firstName', {
|
|
210
|
+
header: 'First',
|
|
211
|
+
cell: (i) => i.getValue(),
|
|
212
|
+
}),
|
|
213
|
+
columnHelper.display({
|
|
214
|
+
id: 'actions',
|
|
215
|
+
header: 'Actions',
|
|
216
|
+
cell: () => 'Edit',
|
|
217
|
+
}),
|
|
218
|
+
])
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
If you don't want to repeat `TFeatures` everywhere, use `createTableHook(...)`
|
|
222
|
+
and the resulting `createAppColumnHelper<Person>()` which pre-binds features.
|
|
223
|
+
|
|
224
|
+
Every public type now requires `TFeatures` (`ColumnDef<TFeatures, TData, TValue>`,
|
|
225
|
+
`Cell<TFeatures, TData, TValue>`, etc.). Full mapping →
|
|
226
|
+
[`references/v8-to-v9-mapping.md`](references/v8-to-v9-mapping.md#type-generics--every-type-takes-tfeatures-now).
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 6. Rendering — directive-based, with shorthand directives
|
|
231
|
+
|
|
232
|
+
v8 Angular rendering was already directive-flavored, but v9 adds the
|
|
233
|
+
**shorthand directives** (`*flexRenderCell`, `*flexRenderHeader`,
|
|
234
|
+
`*flexRenderFooter`) that auto-resolve the column-def slot and context. Prefer
|
|
235
|
+
them over the long `*flexRender="… ; props: …"` form.
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<!-- v8 / v9 long form (still works) -->
|
|
239
|
+
<td
|
|
240
|
+
*flexRender="cell.column.columnDef.cell; props: cell.getContext(); let rendered"
|
|
241
|
+
>
|
|
242
|
+
{{ rendered }}
|
|
243
|
+
</td>
|
|
244
|
+
|
|
245
|
+
<!-- v9 shorthand — recommended -->
|
|
246
|
+
<td *flexRenderCell="cell; let value">{{ value }}</td>
|
|
247
|
+
<th *flexRenderHeader="header; let value">{{ value }}</th>
|
|
248
|
+
<th *flexRenderFooter="footer; let value">{{ value }}</th>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import { FlexRender } from '@tanstack/angular-table' // ← imports both directives
|
|
253
|
+
@Component({ imports: [FlexRender], ... })
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
v9-only:
|
|
257
|
+
|
|
258
|
+
- `flexRenderComponent(Component, { inputs, outputs, bindings, directives, injector })`
|
|
259
|
+
for explicit component rendering.
|
|
260
|
+
- DI tokens (`TanStackTable` / `TanStackTableHeader` / `TanStackTableCell`
|
|
261
|
+
directives + `injectTableContext()` / `injectTableHeaderContext()` /
|
|
262
|
+
`injectTableCellContext()` / `injectFlexRenderContext()`) — no more input
|
|
263
|
+
drilling.
|
|
264
|
+
- Column-def `cell` / `header` / `footer` functions run inside
|
|
265
|
+
`runInInjectionContext`, so `inject(...)` and signals work in them.
|
|
266
|
+
|
|
267
|
+
See `tanstack-table/angular/angular-rendering-directives` for the full surface.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 7. Reactivity model — signals replace v8 memo accessors
|
|
272
|
+
|
|
273
|
+
v8 backed reactivity with manual memoized getters. v9's adapter
|
|
274
|
+
(`angularReactivity(injector)`) backs every readonly atom with an Angular
|
|
275
|
+
`computed` and every writable atom with an Angular `signal`. Consequences:
|
|
276
|
+
|
|
277
|
+
- **No `toSignal(...)` adapters around table state.** Read `table.atoms.x.get()`
|
|
278
|
+
/ `table.store.state.x` directly inside templates, `computed`, `effect`.
|
|
279
|
+
- **`computed(...)` is for derivation / equality, not for "make it reactive".**
|
|
280
|
+
Use `{ equal: shallow }` from `@tanstack/angular-table` on object/array
|
|
281
|
+
slices to skip downstream work on no-op updates.
|
|
282
|
+
- **The `injectTable` initializer re-runs on signal changes.** Don't put
|
|
283
|
+
expensive object literals in there.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 8. Renames at a glance
|
|
288
|
+
|
|
289
|
+
- `sortingFn` → `sortFn`, `sortingFns` → `sortFns`, `SortingFn` → `SortFn`
|
|
290
|
+
(full table in [`references/v8-to-v9-mapping.md`](references/v8-to-v9-mapping.md#naming-renames--sorting)).
|
|
291
|
+
- `enablePinning` → `enableColumnPinning` / `enableRowPinning` (split).
|
|
292
|
+
- `columnSizingInfo` state → `columnResizing` state (sizing/resizing split into
|
|
293
|
+
two features — see [`references/v8-to-v9-mapping.md`](references/v8-to-v9-mapping.md#column-sizing-vs-resizing--split)).
|
|
294
|
+
- All `_`-prefixed internal APIs removed; use the public equivalents.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Migration checklist
|
|
299
|
+
|
|
300
|
+
- [ ] Replace `createAngularTable` import + call with `injectTable`.
|
|
301
|
+
- [ ] Add `_features: tableFeatures({...})` (or `stockFeatures`) — required.
|
|
302
|
+
- [ ] Convert every `get*RowModel()` option to a `_rowModels.<slot>` entry with
|
|
303
|
+
the matching `create*RowModel(...)` factory.
|
|
304
|
+
- [ ] Add `filterFns` / `sortFns` / `aggregationFns` as **factory parameters**
|
|
305
|
+
where needed.
|
|
306
|
+
- [ ] Update `createColumnHelper<Person>()` → `createColumnHelper<typeof _features, Person>()`.
|
|
307
|
+
- [ ] Update every `ColumnDef<Person>` / `Cell<Person, X>` etc. to include
|
|
308
|
+
`TFeatures`.
|
|
309
|
+
- [ ] Replace `table.getState()` reads with `table.store.state` (or
|
|
310
|
+
`table.atoms.<slice>.get()` for per-slice reactivity).
|
|
311
|
+
- [ ] Remove any usage of the v8 single `onStateChange` — split into per-slice
|
|
312
|
+
`on[State]Change`.
|
|
313
|
+
- [ ] In `on[State]Change` callbacks, handle both value and updater-fn shapes.
|
|
314
|
+
- [ ] Move `columns`, `_features`, `_rowModels` **outside** the `injectTable`
|
|
315
|
+
initializer.
|
|
316
|
+
- [ ] Switch any `flexRender` long-form to `*flexRenderCell` / `*flexRenderHeader` /
|
|
317
|
+
`*flexRenderFooter` shorthand where applicable.
|
|
318
|
+
- [ ] Where you need component rendering with explicit options, switch wrapper
|
|
319
|
+
shape to `flexRenderComponent(Component, { inputs, outputs, ... })`.
|
|
320
|
+
- [ ] Replace prop-drilled cell/header inputs with
|
|
321
|
+
`injectTableCellContext()` / `injectTableHeaderContext()` /
|
|
322
|
+
`injectFlexRenderContext()` (optional but worthwhile).
|
|
323
|
+
- [ ] Rename `sortingFn` → `sortFn`, `getSortingFn` → `getSortFn`,
|
|
324
|
+
`sortingFns` → `sortFns`, `SortingFn` → `SortFn`.
|
|
325
|
+
- [ ] Replace `columnSizingInfo` state / setters / change handler with the
|
|
326
|
+
`columnResizing` equivalents; add `columnResizingFeature` to `_features`
|
|
327
|
+
if you actually drag-resize.
|
|
328
|
+
- [ ] Replace `enablePinning` with `enableColumnPinning` / `enableRowPinning`.
|
|
329
|
+
- [ ] Update `ColumnMeta` module augmentation to include the `TFeatures`
|
|
330
|
+
generic.
|
|
331
|
+
- [ ] Drop any `_`-prefixed internal API usages; replace with public
|
|
332
|
+
equivalents.
|
|
333
|
+
- [ ] (Optional) Adopt `tableOptions(...)` for shared base config.
|
|
334
|
+
- [ ] (Optional) Adopt `createTableHook(...)` for app-wide table infrastructure.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Failure modes
|
|
339
|
+
|
|
340
|
+
### 1. (CRITICAL) Leaving `getCoreRowModel()` / `getSortedRowModel()` / etc. in v9 options
|
|
341
|
+
|
|
342
|
+
These options don't exist anymore. They become `_rowModels` entries with
|
|
343
|
+
factory functions. The TypeScript error is loud but agents sometimes silence
|
|
344
|
+
it with `as any` — don't.
|
|
345
|
+
|
|
346
|
+
### 2. (CRITICAL) Reaching for `createAngularTable` from v8 muscle memory
|
|
347
|
+
|
|
348
|
+
Always `injectTable(() => ({...}))`. The injection-context requirement means
|
|
349
|
+
it must run from a class field, constructor, or
|
|
350
|
+
`runInInjectionContext(injector, () => injectTable(...))`.
|
|
351
|
+
|
|
352
|
+
### 3. (CRITICAL) Registering a feature but forgetting its row model
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
// ❌ filtering enabled, but no filtered row model — UI changes, rows don't filter
|
|
356
|
+
_features: tableFeatures({ columnFilteringFeature })
|
|
357
|
+
_rowModels: {
|
|
358
|
+
} // missing filteredRowModel
|
|
359
|
+
|
|
360
|
+
// ✅
|
|
361
|
+
_rowModels: {
|
|
362
|
+
filteredRowModel: createFilteredRowModel(filterFns)
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Same for sorting, pagination, expanding, grouping, faceting. Selection,
|
|
367
|
+
visibility, ordering, pinning, sizing, resizing do **not** need a row model.
|
|
368
|
+
|
|
369
|
+
### 4. (HIGH) `getState()` → `table.store.state` text replacement loses reactivity
|
|
370
|
+
|
|
371
|
+
Bulk-replacing `table.getState().x` with `table.store.state.x` works for _current
|
|
372
|
+
value_ reads, but if you used a `computed`/`memo` around `getState()` for
|
|
373
|
+
reactivity, switch to `table.atoms.x.get()` — it's already signal-backed and
|
|
374
|
+
needs no wrapper.
|
|
375
|
+
|
|
376
|
+
### 5. (HIGH) Stale `sortingFn` / `sortingFns` references in column defs
|
|
377
|
+
|
|
378
|
+
The rename is mechanical: `sortingFn` → `sortFn`, `sortingFns` → `sortFns`,
|
|
379
|
+
`getSortingFn` → `getSortFn`. Missed renames produce silent runtime fallbacks
|
|
380
|
+
to default sort.
|
|
381
|
+
|
|
382
|
+
### 6. (HIGH) Column helper using v8 generic order
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
// ❌ TS will complain — the first generic is TFeatures, not TData
|
|
386
|
+
const columnHelper = createColumnHelper<Person>()
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### 7. (HIGH) Putting `_features` / `columns` / row-model factories inside the `injectTable` initializer
|
|
390
|
+
|
|
391
|
+
The v8 mental model was "build columns inside the hook". v9's
|
|
392
|
+
`injectTable` initializer re-runs on every signal read change — keep heavy
|
|
393
|
+
literals outside.
|
|
394
|
+
|
|
395
|
+
Lower-severity failure modes (MEDIUM/LOW: `stockFeatures` cleanup, `enablePinning`
|
|
396
|
+
removal, `columnSizingInfo` rename, single-handler porting, hand-rolled
|
|
397
|
+
`TFeatures` in render fns, `_`-prefix internal usage, reimplementing built-in
|
|
398
|
+
APIs, `ColumnMeta` augmentation drift, `flexRender` as a function, mixing v8/v9
|
|
399
|
+
atoms) → [`references/v8-to-v9-mapping.md`](references/v8-to-v9-mapping.md#lower-severity-failure-modes-mediumlow).
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## References
|
|
404
|
+
|
|
405
|
+
- [Full v8 → v9 mapping tables (row models, features, types, renames, MEDIUM failure modes)](references/v8-to-v9-mapping.md)
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## See also
|
|
410
|
+
|
|
411
|
+
- `tanstack-table/angular/getting-started` — what the v9 target shape looks like
|
|
412
|
+
- `tanstack-table/angular/table-state` — signal-backed atom model
|
|
413
|
+
- `tanstack-table/angular/angular-rendering-directives` — full rendering API
|
|
414
|
+
- `tanstack-table/angular/production-readiness` — once compiling, optimize the bundle
|
|
415
|
+
- `tanstack-table/core/migrate-v8-to-v9` — framework-agnostic core changes
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# v8 → v9 Mapping Tables — Full Reference
|
|
2
|
+
|
|
3
|
+
Mechanical translation tables and detailed renames for the Angular Table v8 →
|
|
4
|
+
v9 migration. The SKILL.md keeps the primary patterns; this file is the
|
|
5
|
+
exhaustive lookup.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Row-model migration table
|
|
10
|
+
|
|
11
|
+
| v8 option | v9 `_rowModels` key | v9 factory |
|
|
12
|
+
| -------------------------- | --------------------- | --------------------------------------- |
|
|
13
|
+
| `getCoreRowModel()` | (automatic) | — |
|
|
14
|
+
| `getFilteredRowModel()` | `filteredRowModel` | `createFilteredRowModel(filterFns)` |
|
|
15
|
+
| `getSortedRowModel()` | `sortedRowModel` | `createSortedRowModel(sortFns)` |
|
|
16
|
+
| `getPaginationRowModel()` | `paginatedRowModel` | `createPaginatedRowModel()` |
|
|
17
|
+
| `getExpandedRowModel()` | `expandedRowModel` | `createExpandedRowModel()` |
|
|
18
|
+
| `getGroupedRowModel()` | `groupedRowModel` | `createGroupedRowModel(aggregationFns)` |
|
|
19
|
+
| `getFacetedRowModel()` | `facetedRowModel` | `createFacetedRowModel()` |
|
|
20
|
+
| `getFacetedMinMaxValues()` | `facetedMinMaxValues` | `createFacetedMinMaxValues()` |
|
|
21
|
+
| `getFacetedUniqueValues()` | `facetedUniqueValues` | `createFacetedUniqueValues()` |
|
|
22
|
+
|
|
23
|
+
## Feature registration table
|
|
24
|
+
|
|
25
|
+
| v8 (implicit) | v9 feature import |
|
|
26
|
+
| --------------- | ------------------------- |
|
|
27
|
+
| filter columns | `columnFilteringFeature` |
|
|
28
|
+
| global filter | `globalFilteringFeature` |
|
|
29
|
+
| sort rows | `rowSortingFeature` |
|
|
30
|
+
| pagination | `rowPaginationFeature` |
|
|
31
|
+
| row selection | `rowSelectionFeature` |
|
|
32
|
+
| expanding rows | `rowExpandingFeature` |
|
|
33
|
+
| pin rows | `rowPinningFeature` |
|
|
34
|
+
| pin columns | `columnPinningFeature` |
|
|
35
|
+
| hide columns | `columnVisibilityFeature` |
|
|
36
|
+
| reorder columns | `columnOrderingFeature` |
|
|
37
|
+
| size columns | `columnSizingFeature` |
|
|
38
|
+
| resize columns | `columnResizingFeature` |
|
|
39
|
+
| group columns | `columnGroupingFeature` |
|
|
40
|
+
| facet columns | `columnFacetingFeature` |
|
|
41
|
+
|
|
42
|
+
> If you don't want to think about tree-shaking yet, you can pass
|
|
43
|
+
> `stockFeatures`:
|
|
44
|
+
>
|
|
45
|
+
> ```ts
|
|
46
|
+
> import { stockFeatures } from '@tanstack/angular-table'
|
|
47
|
+
> _features: stockFeatures
|
|
48
|
+
> ```
|
|
49
|
+
>
|
|
50
|
+
> This restores v8-like "everything bundled" behavior — but the v9 bundle
|
|
51
|
+
> wins are gone. Plan to migrate to a curated `tableFeatures({...})` as part of
|
|
52
|
+
> productionization.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Type generics — every type takes `TFeatures` now
|
|
57
|
+
|
|
58
|
+
```txt
|
|
59
|
+
v8 v9
|
|
60
|
+
--- ---
|
|
61
|
+
Column<TData> → Column<TFeatures, TData, TValue>
|
|
62
|
+
ColumnDef<TData> → ColumnDef<TFeatures, TData, TValue>
|
|
63
|
+
Table<TData> → Table<TFeatures, TData>
|
|
64
|
+
Row<TData> → Row<TFeatures, TData>
|
|
65
|
+
Cell<TData, TValue> → Cell<TFeatures, TData, TValue>
|
|
66
|
+
Header<TData, TValue> → Header<TFeatures, TData, TValue>
|
|
67
|
+
HeaderContext<TData, TValue> → HeaderContext<TFeatures, TData, TValue>
|
|
68
|
+
CellContext<TData, TValue> → CellContext<TFeatures, TData, TValue>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Easiest fix: extract `typeof _features` once.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const _features = tableFeatures({ rowSortingFeature, columnFilteringFeature })
|
|
75
|
+
|
|
76
|
+
type Features = typeof _features
|
|
77
|
+
|
|
78
|
+
const columns: Array<ColumnDef<Features, Person>> = [
|
|
79
|
+
/* … */
|
|
80
|
+
]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If you're on `stockFeatures`:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import type { StockFeatures, ColumnDef } from '@tanstack/angular-table'
|
|
87
|
+
const columns: Array<ColumnDef<StockFeatures, Person>> = [
|
|
88
|
+
/* … */
|
|
89
|
+
]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`ColumnMeta` module augmentation also needs `TFeatures`:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
declare module '@tanstack/angular-table' {
|
|
96
|
+
interface ColumnMeta<
|
|
97
|
+
TFeatures extends TableFeatures,
|
|
98
|
+
TData extends RowData,
|
|
99
|
+
TValue,
|
|
100
|
+
> {
|
|
101
|
+
align?: 'left' | 'right'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Naming renames — sorting
|
|
109
|
+
|
|
110
|
+
| v8 | v9 |
|
|
111
|
+
| ----------------------------------- | ------------------------ |
|
|
112
|
+
| `sortingFn` (column-def field) | `sortFn` |
|
|
113
|
+
| `column.getSortingFn()` | `column.getSortFn()` |
|
|
114
|
+
| `column.getAutoSortingFn()` | `column.getAutoSortFn()` |
|
|
115
|
+
| `SortingFn` type | `SortFn` |
|
|
116
|
+
| `SortingFns` interface | `SortFns` |
|
|
117
|
+
| `sortingFns` (built-in fn registry) | `sortFns` |
|
|
118
|
+
|
|
119
|
+
Find-and-replace, then update `createSortedRowModel(sortFns)`.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Column sizing vs resizing — split
|
|
124
|
+
|
|
125
|
+
v8 combined sizing and resizing into one feature. v9 splits them so you can
|
|
126
|
+
ship only what you use.
|
|
127
|
+
|
|
128
|
+
| v8 | v9 |
|
|
129
|
+
| --------------------------------- | ---------------------------------------------------------- |
|
|
130
|
+
| `ColumnSizing` (single feature) | `columnSizingFeature` + `columnResizingFeature` (separate) |
|
|
131
|
+
| `columnSizingInfo` state | `columnResizing` state |
|
|
132
|
+
| `setColumnSizingInfo()` | `setColumnResizing()` |
|
|
133
|
+
| `onColumnSizingInfoChange` option | `onColumnResizingChange` option |
|
|
134
|
+
|
|
135
|
+
If you only render fixed-width columns and never drag-to-resize, import only
|
|
136
|
+
`columnSizingFeature`.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Pinning option split
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// v8
|
|
144
|
+
enablePinning: true
|
|
145
|
+
|
|
146
|
+
// v9 — explicit
|
|
147
|
+
enableColumnPinning: true
|
|
148
|
+
enableRowPinning: true
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Row API: privates promoted to public
|
|
154
|
+
|
|
155
|
+
| v8 | v9 |
|
|
156
|
+
| ---------------------------------------- | -------------------------------------- |
|
|
157
|
+
| `row._getAllCellsByColumnId()` (private) | `row.getAllCellsByColumnId()` (public) |
|
|
158
|
+
|
|
159
|
+
All other `_`-prefixed internal APIs from v8 are removed in v9 — use the
|
|
160
|
+
public equivalents. If you were touching `_`-prefixed members, you were on
|
|
161
|
+
unsupported territory; v9 forces the fix.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## `tableOptions(...)` — new composition helper
|
|
166
|
+
|
|
167
|
+
v9 ships `tableOptions(...)` for type-safe partial option composition. Useful
|
|
168
|
+
during migration if you have shared base config:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { tableOptions, tableFeatures, rowSortingFeature } from '@tanstack/angular-table'
|
|
172
|
+
|
|
173
|
+
const baseOptions = tableOptions({
|
|
174
|
+
_features: tableFeatures({ rowSortingFeature }),
|
|
175
|
+
debugTable: isDevMode(),
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
readonly table = injectTable(() => ({
|
|
179
|
+
...baseOptions,
|
|
180
|
+
_rowModels: { /* … */ },
|
|
181
|
+
columns: this.columns,
|
|
182
|
+
data: this.data(),
|
|
183
|
+
}))
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
And for whole-app patterns, `createTableHook(...)` — see
|
|
187
|
+
`tanstack-table/angular/angular-rendering-directives`.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## `RowData` type tightened
|
|
192
|
+
|
|
193
|
+
`RowData` is now stricter (object-like; no primitives). If you had
|
|
194
|
+
`type Row = string`, that won't fly in v9 — wrap it in an object.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Lower-severity failure modes (MEDIUM/LOW)
|
|
199
|
+
|
|
200
|
+
### Skipping `stockFeatures` cleanup later
|
|
201
|
+
|
|
202
|
+
Using `stockFeatures` is a fine migration shortcut, but it forgoes the v9
|
|
203
|
+
bundle wins. Once everything compiles, swap `stockFeatures` for an explicit
|
|
204
|
+
`tableFeatures({...})` listing only the features you use.
|
|
205
|
+
|
|
206
|
+
### Forgetting `enablePinning` is gone
|
|
207
|
+
|
|
208
|
+
`enablePinning: true` silently does nothing. Use `enableColumnPinning: true`
|
|
209
|
+
and/or `enableRowPinning: true`.
|
|
210
|
+
|
|
211
|
+
### Forgetting `columnSizingInfo` is gone
|
|
212
|
+
|
|
213
|
+
Replace state name `columnSizingInfo` with `columnResizing`, setter
|
|
214
|
+
`setColumnSizingInfo` with `setColumnResizing`, handler
|
|
215
|
+
`onColumnSizingInfoChange` with `onColumnResizingChange`. And add
|
|
216
|
+
`columnResizingFeature` to `_features` if you actually need resizing.
|
|
217
|
+
|
|
218
|
+
### Single global `onStateChange` ported as a giant per-slice fan-out
|
|
219
|
+
|
|
220
|
+
In v9 each slice has its own callback. If you previously used `onStateChange`
|
|
221
|
+
to multiplex changes, port to the specific `on[State]Change` callbacks you
|
|
222
|
+
actually care about — don't recreate a megaswitch.
|
|
223
|
+
|
|
224
|
+
### Hand-rolling `TFeatures` in render-fn types
|
|
225
|
+
|
|
226
|
+
When a `cell` / `header` function signature requires `CellContext<TFeatures, TData, TValue>`,
|
|
227
|
+
let `createColumnHelper<typeof _features, TData>()` infer it for you. Spelling
|
|
228
|
+
features by hand in dozens of render-fn signatures is a sign you should be
|
|
229
|
+
using `createAppColumnHelper` from `createTableHook`.
|
|
230
|
+
|
|
231
|
+
### Reaching for `_`-prefixed internals because the public method "doesn't exist"
|
|
232
|
+
|
|
233
|
+
The "missing" method usually means the feature isn't in `_features`. Add the
|
|
234
|
+
feature; don't peek at internals.
|
|
235
|
+
|
|
236
|
+
### Reimplementing what the table API already does
|
|
237
|
+
|
|
238
|
+
Symptoms of v8 muscle memory carrying through:
|
|
239
|
+
|
|
240
|
+
- Manually sorting the data signal in `effect(...)` instead of
|
|
241
|
+
`table.setSorting(...)` and using `table.getRowModel().rows`.
|
|
242
|
+
- Manually paginating the rows array instead of using `paginatedRowModel`.
|
|
243
|
+
- Hand-rolling `getSelectedRowModel().flatRows` from a `rowSelection` signal.
|
|
244
|
+
|
|
245
|
+
If a v8 escape hatch was needed because of a bug or missing API, check the v9
|
|
246
|
+
public API first — many things were added in v9.
|
|
247
|
+
|
|
248
|
+
### `ColumnMeta` augmentation without the `TFeatures` generic
|
|
249
|
+
|
|
250
|
+
The interface now takes `TFeatures` first. Old declarations get silently merged
|
|
251
|
+
but typed wrong.
|
|
252
|
+
|
|
253
|
+
### Importing `flexRender` as a function
|
|
254
|
+
|
|
255
|
+
There's no `flexRender(fn, ctx)` in Angular. `FlexRender` is a directive tuple
|
|
256
|
+
constant. Imports + template directive form is the only shape.
|
|
257
|
+
|
|
258
|
+
### Trying to share v9 atoms with v8 — incompatible
|
|
259
|
+
|
|
260
|
+
If you have a partial v8 codebase coexisting, **don't** try to bridge atoms
|
|
261
|
+
across the version boundary. Migrate per-component.
|