@tanstack/angular-table 9.0.0-beta.38 → 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.
Files changed (25) hide show
  1. package/README.md +1 -0
  2. package/dist/README.md +1 -0
  3. package/package.json +2 -2
  4. package/skills/create-table-hook/SKILL.md +148 -0
  5. package/skills/getting-started/SKILL.md +138 -0
  6. package/skills/migrate-v8-to-v9/SKILL.md +194 -0
  7. package/skills/table-state/SKILL.md +197 -0
  8. package/skills/with-tanstack-query/SKILL.md +142 -0
  9. package/skills/with-tanstack-virtual/SKILL.md +126 -0
  10. package/skills/angular/angular-rendering-directives/SKILL.md +0 -415
  11. package/skills/angular/angular-rendering-directives/references/content-shapes.md +0 -142
  12. package/skills/angular/angular-rendering-directives/references/create-table-hook-registries.md +0 -89
  13. package/skills/angular/angular-rendering-directives/references/di-tokens.md +0 -171
  14. package/skills/angular/angular-rendering-directives/references/flex-render-component-options.md +0 -64
  15. package/skills/angular/client-to-server/SKILL.md +0 -468
  16. package/skills/angular/compose-with-tanstack-query/SKILL.md +0 -486
  17. package/skills/angular/compose-with-tanstack-store/SKILL.md +0 -405
  18. package/skills/angular/compose-with-tanstack-virtual/SKILL.md +0 -399
  19. package/skills/angular/getting-started/SKILL.md +0 -487
  20. package/skills/angular/getting-started/references/feature-row-model-mapping.md +0 -51
  21. package/skills/angular/migrate-v8-to-v9/SKILL.md +0 -422
  22. package/skills/angular/migrate-v8-to-v9/references/v8-to-v9-mapping.md +0 -268
  23. package/skills/angular/production-readiness/SKILL.md +0 -472
  24. package/skills/angular/table-state/SKILL.md +0 -422
  25. package/skills/angular/table-state/references/external-atoms-and-app-hook.md +0 -153
package/README.md CHANGED
@@ -40,6 +40,7 @@
40
40
  > - [Svelte Table](https://tanstack.com/table/alpha/docs/framework/svelte/svelte-table)
41
41
  > - [Vue Table](https://tanstack.com/table/alpha/docs/framework/vue/vue-table)
42
42
  > - [Alpine Table](https://tanstack.com/table/alpha/docs/framework/alpine/alpine-table)
43
+ > - [Ember Table](https://tanstack.com/table/alpha/docs/framework/ember/ember-table)
43
44
 
44
45
  A headless table library for building powerful datagrids with full control over markup, styles, and behavior.
45
46
 
package/dist/README.md CHANGED
@@ -40,6 +40,7 @@
40
40
  > - [Svelte Table](https://tanstack.com/table/alpha/docs/framework/svelte/svelte-table)
41
41
  > - [Vue Table](https://tanstack.com/table/alpha/docs/framework/vue/vue-table)
42
42
  > - [Alpine Table](https://tanstack.com/table/alpha/docs/framework/alpine/alpine-table)
43
+ > - [Ember Table](https://tanstack.com/table/alpha/docs/framework/ember/ember-table)
43
44
 
44
45
  A headless table library for building powerful datagrids with full control over markup, styles, and behavior.
45
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/angular-table",
3
- "version": "9.0.0-beta.38",
3
+ "version": "9.0.0-beta.42",
4
4
  "description": "Headless UI for building powerful tables & datagrids for Angular.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -57,7 +57,7 @@
57
57
  "dependencies": {
58
58
  "@tanstack/angular-store": "^0.11.0",
59
59
  "tslib": "^2.8.1",
60
- "@tanstack/table-core": "9.0.0-beta.38"
60
+ "@tanstack/table-core": "9.0.0-beta.42"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@analogjs/vite-plugin-angular": "^2.6.1",
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: create-table-hook
3
+ description: >
4
+ Create an Angular injectAppTable/createAppColumnHelper abstraction with shared features/defaults, registered components, injectTableContext/injectTableCellContext/injectTableHeaderContext, and correct FlexRender component-versus-function handling.
5
+ metadata:
6
+ type: framework
7
+ library: '@tanstack/angular-table'
8
+ framework: angular
9
+ library_version: '9.0.0-beta.42'
10
+ requires:
11
+ - '@tanstack/table-core#core'
12
+ - getting-started
13
+ - table-state
14
+ sources:
15
+ - 'TanStack/table:docs/framework/angular/guide/composable-tables.md'
16
+ - 'TanStack/table:examples/angular/composable-tables'
17
+ - 'TanStack/table:packages/angular-table/src/helpers/createTableHook.ts'
18
+ ---
19
+
20
+ This skill builds on `@tanstack/table-core#core`, `getting-started`, and `table-state`. Use it for repeated app conventions; keep one-off tables on `injectTable`.
21
+
22
+ ## Setup
23
+
24
+ ```ts
25
+ import {
26
+ createTableHook,
27
+ rowSortingFeature,
28
+ tableFeatures,
29
+ } from '@tanstack/angular-table'
30
+
31
+ export const {
32
+ injectAppTable,
33
+ createAppColumnHelper,
34
+ injectTableContext,
35
+ injectTableCellContext,
36
+ injectTableHeaderContext,
37
+ } = createTableHook({
38
+ features: tableFeatures({ rowSortingFeature }),
39
+ })
40
+ ```
41
+
42
+ ```ts
43
+ const helper = createAppColumnHelper<Person>()
44
+ const columns = helper.columns([helper.accessor('name', { header: 'Name' })])
45
+
46
+ export class PeopleTable {
47
+ readonly table = injectAppTable(() => ({ columns, data: this.data() }))
48
+ }
49
+ ```
50
+
51
+ ## Core Patterns
52
+
53
+ ### Consume typed DI context in registered components
54
+
55
+ ```ts
56
+ export class NameCell {
57
+ readonly cell = injectTableCellContext<string, Person>()
58
+ readonly value = computed(() => this.cell().getValue())
59
+ }
60
+ ```
61
+
62
+ Use the matching table/header/cell injector instead of threading context props through reusable components.
63
+
64
+ ### Distinguish component types from render functions
65
+
66
+ Register either an Angular component type or a render function. Return component types directly when FlexRender should set context inputs; use `flexRenderComponent(Component, options)` only for explicit inputs/outputs/injector/bindings/directives.
67
+
68
+ ## Common Mistakes
69
+
70
+ ### CRITICAL Calling app helpers outside DI
71
+
72
+ Wrong:
73
+
74
+ ```ts
75
+ export function make() {
76
+ return injectAppTable(() => options)
77
+ }
78
+ ```
79
+
80
+ Correct:
81
+
82
+ ```ts
83
+ export class PeopleTable {
84
+ readonly table = injectAppTable(() => options())
85
+ }
86
+ ```
87
+
88
+ Both app-table construction and returned context injectors require Angular injection context.
89
+
90
+ Source: `packages/angular-table/src/helpers/createTableHook.ts`
91
+
92
+ ### HIGH Prop drilling registered context
93
+
94
+ Wrong:
95
+
96
+ ```ts
97
+ cell: (ctx) => flexRenderComponent(NameCell, { inputs: { cell: ctx.cell } })
98
+ ```
99
+
100
+ Correct:
101
+
102
+ ```ts
103
+ cell: (ctx) => ctx.cell.NameCell
104
+ ```
105
+
106
+ Registered components can consume the app hook’s typed cell context directly.
107
+
108
+ Source: `docs/framework/angular/guide/composable-tables.md`
109
+
110
+ ### HIGH Wrapping a function as a component
111
+
112
+ Wrong:
113
+
114
+ ```ts
115
+ flexRenderComponent((props) => props.cell.getValue())
116
+ ```
117
+
118
+ Correct:
119
+
120
+ ```ts
121
+ ;(props) => props.cell.getValue()
122
+ ```
123
+
124
+ `flexRenderComponent` validates an Angular component type; plain render functions are already valid render content.
125
+
126
+ Source: `packages/angular-table/src/flex-render/flexRenderComponent.ts`
127
+
128
+ ### MEDIUM Abstracting a one-off table
129
+
130
+ Wrong:
131
+
132
+ ```ts
133
+ const hook = createTableHook({ features: tableFeatures({}) })
134
+ ```
135
+
136
+ Correct:
137
+
138
+ ```ts
139
+ readonly table = injectTable(() => ({ features, columns, data: this.data() }))
140
+ ```
141
+
142
+ Use the app hook only when shared defaults, types, or registered components justify it.
143
+
144
+ Source: `docs/framework/angular/guide/composable-tables.md`
145
+
146
+ ## API Discovery
147
+
148
+ Inspect `node_modules/@tanstack/angular-table/src/helpers/createTableHook.ts`, `helpers/{table,cell,header}.ts`, and `flex-render/` for exact DI and rendering contracts.
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: getting-started
3
+ description: >
4
+ Create an Angular TanStack Table v9 table with injectTable inside injection context, explicit stable tableFeatures and columns, signal-backed data, and FlexRender structural directives or helpers.
5
+ metadata:
6
+ type: framework
7
+ library: '@tanstack/angular-table'
8
+ framework: angular
9
+ library_version: '9.0.0-beta.42'
10
+ requires:
11
+ - '@tanstack/table-core#core'
12
+ - '@tanstack/table-core#table-features'
13
+ sources:
14
+ - 'TanStack/table:docs/framework/angular/guide/migrating.md'
15
+ - 'TanStack/table:docs/framework/angular/guide/rendering.md'
16
+ - 'TanStack/table:examples/angular/basic-inject-table'
17
+ - 'TanStack/table:packages/angular-table/src/index.ts'
18
+ ---
19
+
20
+ This skill builds on `@tanstack/table-core#core` and `@tanstack/table-core#table-features`. Read them first for the headless model and explicit features.
21
+
22
+ ## Setup
23
+
24
+ ```ts
25
+ import { Component, signal } from '@angular/core'
26
+ import { FlexRender, injectTable, tableFeatures } from '@tanstack/angular-table'
27
+
28
+ type Person = { name: string; age: number }
29
+ const features = tableFeatures({})
30
+ const columns = [
31
+ { accessorKey: 'name', header: 'Name' },
32
+ { accessorKey: 'age', header: 'Age' },
33
+ ]
34
+
35
+ @Component({
36
+ selector: 'app-table',
37
+ imports: [FlexRender],
38
+ template: `<table>
39
+ <tbody>
40
+ @for (row of table.getRowModel().rows; track row.id) {
41
+ <tr>
42
+ @for (cell of row.getAllCells(); track cell.id) {
43
+ <td>
44
+ <ng-container *flexRenderCell="cell; let value">{{
45
+ value
46
+ }}</ng-container>
47
+ </td>
48
+ }
49
+ </tr>
50
+ }
51
+ </tbody>
52
+ </table>`,
53
+ })
54
+ export class TableComponent {
55
+ readonly data = signal<Person[]>([{ name: 'Ada', age: 36 }])
56
+ readonly table = injectTable(() => ({ features, columns, data: this.data() }))
57
+ }
58
+ ```
59
+
60
+ ## Core Patterns
61
+
62
+ ### Keep static inputs outside the initializer
63
+
64
+ `injectTable` reruns its options initializer when a signal read changes. Define features, row-model factories, and columns at module or stable class scope; read only changing values inside.
65
+
66
+ ### Render each content kind correctly
67
+
68
+ Import `FlexRender` for `*flexRender`, `*flexRenderCell`, `*flexRenderHeader`, and `*flexRenderFooter`. Definitions may yield primitives, `TemplateRef`, component types, or `flexRenderComponent(...)`; Table does not supply markup or CSS.
69
+
70
+ ## Common Mistakes
71
+
72
+ ### CRITICAL Calling injectTable outside DI
73
+
74
+ Wrong:
75
+
76
+ ```ts
77
+ export function makeTable() {
78
+ return injectTable(() => ({ features, columns, data }))
79
+ }
80
+ ```
81
+
82
+ Correct:
83
+
84
+ ```ts
85
+ export class TableComponent {
86
+ readonly table = injectTable(() => ({ features, columns, data: this.data() }))
87
+ }
88
+ ```
89
+
90
+ `injectTable` asserts an Angular injection context and registers lifecycle cleanup there.
91
+
92
+ Source: `packages/angular-table/src/injectTable.ts`
93
+
94
+ ### HIGH Reallocating static options reactively
95
+
96
+ Wrong:
97
+
98
+ ```ts
99
+ injectTable(() => ({
100
+ features: tableFeatures({}),
101
+ columns: makeColumns(),
102
+ data: this.data(),
103
+ }))
104
+ ```
105
+
106
+ Correct:
107
+
108
+ ```ts
109
+ const features = tableFeatures({})
110
+ const columns = makeColumns()
111
+ injectTable(() => ({ features, columns, data: this.data() }))
112
+ ```
113
+
114
+ Every signal change reruns the initializer; rebuilding static inputs invalidates memoized Table work.
115
+
116
+ Source: `packages/angular-table/src/injectTable.ts`
117
+
118
+ ### HIGH Treating a render function as a component
119
+
120
+ Wrong:
121
+
122
+ ```ts
123
+ cell: () => flexRenderComponent(() => 'value')
124
+ ```
125
+
126
+ Correct:
127
+
128
+ ```ts
129
+ cell: () => 'value'
130
+ ```
131
+
132
+ `flexRenderComponent` wraps an Angular component type; ordinary functions and primitives are handled directly by FlexRender.
133
+
134
+ Source: `docs/framework/angular/guide/rendering.md`
135
+
136
+ ## API Discovery
137
+
138
+ Inspect `node_modules/@tanstack/angular-table/src/index.ts`, `injectTable.ts`, `flexRender.ts`, and `flex-render/`; inspect optional feature APIs in installed `@tanstack/table-core/src/features/`.
@@ -0,0 +1,194 @@
1
+ ---
2
+ name: migrate-v8-to-v9
3
+ description: >
4
+ Complete Angular v8-to-v9 migration reference: injectTable and injection context, explicit features and row-model slots, signal/atom state, FlexRender directives, type generics, prototype methods, sorting, sizing, selection, and logical pinning.
5
+ metadata:
6
+ type: lifecycle
7
+ library: '@tanstack/angular-table'
8
+ framework: angular
9
+ library_version: '9.0.0-beta.42'
10
+ requires:
11
+ - '@tanstack/table-core#migrate-v8-to-v9'
12
+ - getting-started
13
+ - table-state
14
+ sources:
15
+ - 'TanStack/table:docs/framework/angular/guide/migrating.md'
16
+ - 'TanStack/table:packages/angular-table/src/index.ts'
17
+ - 'TanStack/table:examples/angular/basic-inject-table'
18
+ ---
19
+
20
+ Use this as the complete breaking-change checklist. V9 is the current API; construction, feature registration, state, rendering, and types must migrate together.
21
+
22
+ Framework prerequisite: Angular 19 or newer (`@angular/core >=19`).
23
+
24
+ ## Recommended Migration Order
25
+
26
+ 1. Replace `createAngularTable` with `injectTable` inside an Angular injection context.
27
+ 2. Hoist static/expensive features and columns outside the reactive initializer.
28
+ 3. Move features, row models, and function registries into `tableFeatures`.
29
+ 4. Update signal/atom state reads and FlexRender usage.
30
+ 5. Apply every shared API and type rename below.
31
+ 6. Treat `stockFeatures` as a temporary audit bridge; explicit features are the production target.
32
+
33
+ ```ts
34
+ const features = tableFeatures({
35
+ rowSortingFeature,
36
+ sortedRowModel: createSortedRowModel(),
37
+ sortFns,
38
+ })
39
+
40
+ class TableCmp {
41
+ readonly table = injectTable(() => ({
42
+ features,
43
+ columns,
44
+ data: this.data(),
45
+ }))
46
+ }
47
+ ```
48
+
49
+ ## Construction and Feature Registration
50
+
51
+ | v8 | v9 |
52
+ | ----------------------------------- | ---------------------------------------------------------- |
53
+ | `createAngularTable(() => options)` | `injectTable(() => options)` in injection context |
54
+ | All features bundled | Required `features: tableFeatures({...})` |
55
+ | `getCoreRowModel()` option | Remove; core row model is automatic |
56
+ | `get*RowModel()` table options | `create*RowModel()` slots in `tableFeatures` |
57
+ | `sortingFns` table option | `sortFns` feature slot |
58
+ | Top-level `onStateChange` | Per-slice callbacks, external atoms, or store subscription |
59
+
60
+ The initializer reruns when signals read inside it change and calls `setOptions`; do not rebuild columns or features there.
61
+
62
+ Feature imports are `columnFilteringFeature`, `globalFilteringFeature`, `rowSortingFeature`, `rowPaginationFeature`, `rowSelectionFeature`, `rowExpandingFeature`, `rowPinningFeature`, `columnPinningFeature`, `columnVisibilityFeature`, `columnOrderingFeature`, `columnSizingFeature`, `columnResizingFeature`, `columnGroupingFeature`, and `columnFacetingFeature`. APIs are feature-gated. Put a feature before its dependent slot in the same `tableFeatures` call.
63
+
64
+ ### Row-model mapping
65
+
66
+ | v8 option | v9 slot and factory |
67
+ | -------------------------- | ------------------------------------------------------------------- |
68
+ | `getFilteredRowModel()` | `filteredRowModel: createFilteredRowModel()` after column filtering |
69
+ | `getSortedRowModel()` | `sortedRowModel: createSortedRowModel()` after row sorting |
70
+ | `getPaginationRowModel()` | `paginatedRowModel: createPaginatedRowModel()` after pagination |
71
+ | `getExpandedRowModel()` | `expandedRowModel: createExpandedRowModel()` after expanding |
72
+ | `getGroupedRowModel()` | `groupedRowModel: createGroupedRowModel()` after grouping |
73
+ | `getFacetedRowModel()` | `facetedRowModel: createFacetedRowModel()` after faceting |
74
+ | `getFacetedMinMaxValues()` | `facetedMinMaxValues: createFacetedMinMaxValues()` |
75
+ | `getFacetedUniqueValues()` | `facetedUniqueValues: createFacetedUniqueValues()` |
76
+
77
+ Factories take no arguments. `filterFns`, `sortFns`, and `aggregationFns` are sibling feature slots.
78
+
79
+ ## Angular State Migration
80
+
81
+ - `table.getState().sorting` becomes `table.atoms.sorting.get()` for narrow signal-backed reads.
82
+ - Use `table.store.get()` only for a full flat snapshot/debug output.
83
+ - Derive selected slices with Angular `computed`; use `shallow` equality for recreated object/array slices when appropriate.
84
+ - Controlled Angular signals are read in `state` and updated through matching `on[State]Change` callbacks; resolve value-or-function updaters.
85
+ - Top-level `onStateChange` is removed. Use per-slice callbacks, external atoms, or `table.store.subscribe` for all changes.
86
+ - Prefer external atoms from `@tanstack/angular-store` through `atoms` for app-owned shared slices. Never provide both an atom and `state` for one slice.
87
+ - Treat `table.baseAtoms` as internal; prefer feature APIs or external atoms.
88
+
89
+ ## Angular Rendering and Composition
90
+
91
+ - Import `FlexRender`/the current `*flexRender` directives from the adapter.
92
+ - Prefer `*flexRenderCell="cell; let value"`, `*flexRenderHeader="header; let value"`, and `*flexRenderFooter="footer; let value"`; they choose the definition and context automatically.
93
+ - General `*flexRender` supports primitives, `TemplateRef`, component types, and `flexRenderComponent(...)` wrappers.
94
+ - Column render functions run in an Angular injection context and may call `inject()` or use signals.
95
+ - Components mounted by FlexRender can call `injectFlexRenderContext()` for the render props.
96
+ - Use `flexRenderComponent(Component, { inputs, outputs, injector, bindings, directives })` for explicit component configuration; creation-time `bindings`/`directives` require the supported Angular version.
97
+ - `tableOptions(...)` composes partial options and may omit data, columns, or features until final assembly.
98
+ - `createTableHook` is optional for repeated application conventions; it returns `injectAppTable` and a feature-bound `createAppColumnHelper`.
99
+
100
+ ## Complete Shared Breaking-Change Map
101
+
102
+ ### Instance methods
103
+
104
+ Row, cell, column, header, and related methods now live on shared prototypes and use `this`. Call them on their instances. Do not destructure/pass them bare or expect them in object spread, `Object.keys`, or JSON. Table methods are not affected.
105
+
106
+ ### Logical column pinning
107
+
108
+ Beta.38 has no physical aliases.
109
+
110
+ | old | new |
111
+ | -------------------------------------------------------------- | ------------------------------------------------------------- |
112
+ | `columnPinning.left` / `.right` | `.start` / `.end` |
113
+ | `column.pin('left' \| 'right')` | `column.pin('start' \| 'end')` |
114
+ | `getIsPinned() === 'left' \| 'right'` | `'start' \| 'end'` |
115
+ | `row.getLeftVisibleCells()` / `getRightVisibleCells()` | `getStartVisibleCells()` / `getEndVisibleCells()` |
116
+ | `getLeftHeaderGroups()` / `getRightHeaderGroups()` | `getStartHeaderGroups()` / `getEndHeaderGroups()` |
117
+ | `getLeftFooterGroups()` / `getRightFooterGroups()` | `getStartFooterGroups()` / `getEndFooterGroups()` |
118
+ | `getLeftFlatHeaders()` / `getRightFlatHeaders()` | `getStartFlatHeaders()` / `getEndFlatHeaders()` |
119
+ | `getLeftLeafHeaders()` / `getRightLeafHeaders()` | `getStartLeafHeaders()` / `getEndLeafHeaders()` |
120
+ | `getLeftLeafColumns()` / `getRightLeafColumns()` | `getStartLeafColumns()` / `getEndLeafColumns()` |
121
+ | `getLeftVisibleLeafColumns()` / `getRightVisibleLeafColumns()` | `getStartVisibleLeafColumns()` / `getEndVisibleLeafColumns()` |
122
+ | `getLeftTotalSize()` / `getRightTotalSize()` | `getStartTotalSize()` / `getEndTotalSize()` |
123
+ | `column.getStart('left')` | `column.getStart('start')` |
124
+ | `column.getAfter('right')` | `column.getAfter('end')` |
125
+ | `column.getIndex('left' \| 'right')` | `column.getIndex('start' \| 'end')` |
126
+
127
+ Prefer CSS logical inset properties. Logical names do not set DOM direction. `columnResizeDirection` is unchanged.
128
+
129
+ ### Pinning, sizing, and resizing
130
+
131
+ - `enablePinning` splits into `enableColumnPinning` and `enableRowPinning`.
132
+ - Interactive resizing requires `columnSizingFeature` and `columnResizingFeature`; fixed sizing needs only sizing.
133
+ - `columnSizingInfo` becomes `columnResizing`.
134
+ - `setColumnSizingInfo()` becomes `setColumnResizing()`.
135
+ - `onColumnSizingInfoChange` becomes `onColumnResizingChange`.
136
+
137
+ ### Sorting, rows, and selection
138
+
139
+ | v8 | v9 |
140
+ | ------------------------------ | ----------------------------- |
141
+ | `sortingFn` | `sortFn` |
142
+ | `sortingFns` | `sortFns` |
143
+ | `getSortingFn()` | `getSortFn()` |
144
+ | `getAutoSortingFn()` | `getAutoSortFn()` |
145
+ | `SortingFn` / `SortingFns` | `SortFn` / `SortFns` |
146
+ | `row._getAllCellsByColumnId()` | `row.getAllCellsByColumnId()` |
147
+
148
+ Other `_`-prefixed internals are removed, including `_getPinnedRows`, `_getFacetedRowModel`, `_getFacetedMinMaxValues`, and `_getFacetedUniqueValues`.
149
+
150
+ `getIsSomeRowsSelected()` and `getIsSomePageRowsSelected()` mean at least one, including all. Use `getIsSomeRowsSelected() && !getIsAllRowsSelected()` or `getIsSomePageRowsSelected() && !getIsAllPageRowsSelected()` for indeterminate UI.
151
+
152
+ ## TypeScript Migration
153
+
154
+ - Most types add `TFeatures` first: `Column<TFeatures, TData, TValue>`, `ColumnDef<TFeatures, TData, TValue>`, `Table<TFeatures, TData>`, `Row<TFeatures, TData>`, and `Cell<TFeatures, TData, TValue>`.
155
+ - Replace `createColumnHelper<Person>()` with `createColumnHelper<typeof features, Person>()`; use `columnHelper.columns([...])` for inference.
156
+ - A `createTableHook` column helper already binds features and needs only `<Person>`.
157
+ - Use `StockFeatures` when using `stockFeatures`.
158
+ - Existing `TableMeta`/`ColumnMeta` declaration merging must add `TFeatures` first. Prefer per-table meta slots using `metaHelper`.
159
+ - Replace global `FilterFns`, `SortFns`, `AggregationFns`, and `FilterMeta` augmentation with registry slots and `filterMeta`; registered keys become typed string references.
160
+ - `RowData` is now `Record<string, any> | Array<any>` rather than `unknown`.
161
+
162
+ ## Common Migration Failures
163
+
164
+ ### CRITICAL: Calling injectTable outside injection context
165
+
166
+ Create it in a component/directive/service field initializer or another valid Angular injection context so ownership and cleanup bind correctly.
167
+
168
+ ### HIGH: Rebuilding static inputs reactively
169
+
170
+ Hoist `features` and `columns`; the initializer reruns for tracked signals.
171
+
172
+ ### HIGH: Leaving row models on table options
173
+
174
+ Move each row model beside its prerequisite feature in `tableFeatures`.
175
+
176
+ ### HIGH: Destructuring instance methods
177
+
178
+ Use `row.getValue('name')`; prototype methods require the original instance and are absent from shallow clones.
179
+
180
+ ## Final Checklist
181
+
182
+ - [ ] `createAngularTable` is replaced by `injectTable` in injection context.
183
+ - [ ] Static inputs are stable outside the signal-tracked initializer.
184
+ - [ ] Features, row models, and registries are in `tableFeatures`; core row model is removed.
185
+ - [ ] State reads use atom-backed signals or store intentionally; `onStateChange` is gone.
186
+ - [ ] Controlled state and external atom ownership do not overlap.
187
+ - [ ] FlexRender directives/helpers are migrated and imported.
188
+ - [ ] Prototype methods, pinning, sizing/resizing, sorting, row, and selection changes are audited.
189
+ - [ ] Helpers, types, meta, registries, and `RowData` use v9 shapes.
190
+ - [ ] Temporary `stockFeatures` usage has an explicit removal plan.
191
+
192
+ ## API Discovery
193
+
194
+ Inspect `node_modules/@tanstack/angular-table/src/index.ts`, `injectTable.ts`, and rendering sources. Verify feature slots and exact beta APIs in `node_modules/@tanstack/table-core/src`; do not reconstruct v9 from v8 memory.