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