@tanstack/angular-table 9.0.0-beta.4 → 9.0.0-beta.43
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 +2 -0
- package/dist/README.md +2 -0
- package/dist/fesm2022/tanstack-angular-table-experimental-worker-plugin.mjs +6 -0
- package/dist/fesm2022/tanstack-angular-table-experimental-worker-plugin.mjs.map +1 -0
- package/dist/fesm2022/tanstack-angular-table.mjs +41 -21
- package/dist/fesm2022/tanstack-angular-table.mjs.map +1 -1
- package/dist/types/tanstack-angular-table-experimental-worker-plugin.d.ts +1 -0
- package/dist/types/tanstack-angular-table.d.ts +10 -19
- package/package.json +13 -8
- package/skills/create-table-hook/SKILL.md +148 -0
- package/skills/getting-started/SKILL.md +138 -0
- package/skills/migrate-v8-to-v9/SKILL.md +194 -0
- package/skills/table-state/SKILL.md +197 -0
- package/skills/with-tanstack-query/SKILL.md +142 -0
- package/skills/with-tanstack-virtual/SKILL.md +126 -0
- package/src/flex-render/flexRenderComponent.ts +2 -2
- package/src/flex-render/view.ts +1 -1
- package/src/helpers/cell.ts +6 -2
- package/src/helpers/createTableHook.ts +44 -26
- package/src/helpers/flexRenderCell.ts +14 -0
- package/src/helpers/header.ts +4 -2
- package/src/helpers/table.ts +4 -2
- package/src/injectTable.ts +7 -12
- package/skills/angular/angular-rendering-directives/SKILL.md +0 -415
- package/skills/angular/angular-rendering-directives/references/content-shapes.md +0 -142
- package/skills/angular/angular-rendering-directives/references/create-table-hook-registries.md +0 -89
- package/skills/angular/angular-rendering-directives/references/di-tokens.md +0 -171
- package/skills/angular/angular-rendering-directives/references/flex-render-component-options.md +0 -64
- package/skills/angular/client-to-server/SKILL.md +0 -467
- package/skills/angular/compose-with-tanstack-query/SKILL.md +0 -482
- package/skills/angular/compose-with-tanstack-store/SKILL.md +0 -397
- package/skills/angular/compose-with-tanstack-virtual/SKILL.md +0 -400
- package/skills/angular/getting-started/SKILL.md +0 -496
- package/skills/angular/getting-started/references/feature-row-model-mapping.md +0 -48
- package/skills/angular/migrate-v8-to-v9/SKILL.md +0 -419
- package/skills/angular/migrate-v8-to-v9/references/v8-to-v9-mapping.md +0 -261
- package/skills/angular/production-readiness/SKILL.md +0 -469
- package/skills/angular/table-state/SKILL.md +0 -429
- package/skills/angular/table-state/references/external-atoms-and-app-hook.md +0 -152
|
@@ -144,10 +144,10 @@ interface FlexRenderOptions<TInputs extends Record<string, any>, TOutputs extend
|
|
|
144
144
|
readonly injector?: Injector;
|
|
145
145
|
}
|
|
146
146
|
type Inputs<T> = {
|
|
147
|
-
[K in keyof T as T[K] extends InputSignal<infer
|
|
147
|
+
[K in keyof T as T[K] extends InputSignal<infer _R> ? K : never]?: T[K] extends InputSignal<infer R> ? R : never;
|
|
148
148
|
};
|
|
149
149
|
type Outputs<T> = {
|
|
150
|
-
[K in keyof T as T[K] extends OutputEmitterRef<infer
|
|
150
|
+
[K in keyof T as T[K] extends OutputEmitterRef<infer _R> ? K : never]?: T[K] extends OutputEmitterRef<infer R> ? OutputEmitterRef<R>['emit'] : never;
|
|
151
151
|
};
|
|
152
152
|
/**
|
|
153
153
|
* Helper function to create a {@link FlexRenderComponent} instance, with better type-safety.
|
|
@@ -362,15 +362,7 @@ declare class FlexRenderDirective<TFeatures extends TableFeatures, TRowData exte
|
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
type SubscribeSource<TValue> = Atom<TValue> | ReadonlyAtom<TValue> | Store<TValue> | ReadonlyStore<TValue>;
|
|
365
|
-
type AngularTable<TFeatures extends TableFeatures, TData extends RowData> = Table<TFeatures, TData
|
|
366
|
-
/**
|
|
367
|
-
* @deprecated Prefer `table.atoms.<slice>.get()` for template/render reads
|
|
368
|
-
* of a specific state slice, or Angular computed values around explicit
|
|
369
|
-
* selectors. `table.store.state` is a current-value snapshot and is easy to
|
|
370
|
-
* misuse in render code.
|
|
371
|
-
*/
|
|
372
|
-
readonly store: Table<TFeatures, TData>['store'];
|
|
373
|
-
};
|
|
365
|
+
type AngularTable<TFeatures extends TableFeatures, TData extends RowData> = Table<TFeatures, TData>;
|
|
374
366
|
/**
|
|
375
367
|
* Creates and returns an Angular-reactive table instance.
|
|
376
368
|
*
|
|
@@ -444,7 +436,7 @@ interface TanStackTableCellContext<TFeatures extends TableFeatures, TData extend
|
|
|
444
436
|
*
|
|
445
437
|
* This token is provided by the {@link TanStackTableCell} directive.
|
|
446
438
|
*/
|
|
447
|
-
declare const TanStackTableCellToken: InjectionToken<Signal<
|
|
439
|
+
declare const TanStackTableCellToken: InjectionToken<Signal<Cell<TableFeatures, RowData, unknown>>>;
|
|
448
440
|
/**
|
|
449
441
|
* Provides a TanStack Table `Cell` instance in Angular DI.
|
|
450
442
|
*
|
|
@@ -516,7 +508,7 @@ interface TanStackTableHeaderContext<TFeatures extends TableFeatures, TData exte
|
|
|
516
508
|
*
|
|
517
509
|
* This token is provided by the {@link TanStackTableHeader} directive.
|
|
518
510
|
*/
|
|
519
|
-
declare const TanStackTableHeaderToken: InjectionToken<Signal<
|
|
511
|
+
declare const TanStackTableHeaderToken: InjectionToken<Signal<Header<TableFeatures, RowData, unknown>>>;
|
|
520
512
|
/**
|
|
521
513
|
* Provides a TanStack Table `Header` instance in Angular DI.
|
|
522
514
|
*
|
|
@@ -573,7 +565,7 @@ declare function injectTableHeaderContext<TFeatures extends TableFeatures, TData
|
|
|
573
565
|
*
|
|
574
566
|
* This token is provided by the {@link TanStackTable} directive.
|
|
575
567
|
*/
|
|
576
|
-
declare const TanStackTableToken: InjectionToken<Signal<
|
|
568
|
+
declare const TanStackTableToken: InjectionToken<Signal<AngularTable<TableFeatures, RowData>>>;
|
|
577
569
|
/**
|
|
578
570
|
* Provides a TanStack Table instance (`AngularTable`) in Angular DI.
|
|
579
571
|
*
|
|
@@ -746,12 +738,12 @@ type CreateTableContextOptions<TFeatures extends TableFeatures, TTableComponents
|
|
|
746
738
|
};
|
|
747
739
|
type CreateTableHookResult<TFeatures extends TableFeatures, TTableComponents extends Record<string, RenderableComponent>, TCellComponents extends Record<string, RenderableComponent>, THeaderComponents extends Record<string, RenderableComponent>> = {
|
|
748
740
|
createAppColumnHelper: <TData extends RowData>() => AppColumnHelper<TFeatures, TData, TCellComponents, THeaderComponents>;
|
|
749
|
-
injectTableContext: <TData extends RowData = RowData>() => Signal<AngularTable<TFeatures, TData
|
|
750
|
-
injectTableHeaderContext: <TValue extends CellData = CellData, TRowData extends RowData = RowData>() => Signal<Header<TFeatures, TRowData, TValue
|
|
751
|
-
injectTableCellContext: <TValue extends CellData = CellData, TRowData extends RowData = RowData>() => Signal<Cell<TFeatures, TRowData, TValue
|
|
741
|
+
injectTableContext: <TData extends RowData = RowData>() => Signal<AngularTable<TFeatures, TData> & TTableComponents>;
|
|
742
|
+
injectTableHeaderContext: <TValue extends CellData = CellData, TRowData extends RowData = RowData>() => Signal<Header<TFeatures, TRowData, TValue> & THeaderComponents>;
|
|
743
|
+
injectTableCellContext: <TValue extends CellData = CellData, TRowData extends RowData = RowData>() => Signal<Cell<TFeatures, TRowData, TValue> & TCellComponents>;
|
|
752
744
|
injectFlexRenderHeaderContext: <TData extends RowData, TValue extends CellData>() => HeaderContext<TFeatures, TData, TValue>;
|
|
753
745
|
injectFlexRenderCellContext: <TData extends RowData, TValue extends CellData>() => CellContext<TFeatures, TData, TValue>;
|
|
754
|
-
injectAppTable: <TData extends RowData>(tableOptions: () => Omit<TableOptions<TFeatures, TData>, 'features'
|
|
746
|
+
injectAppTable: <TData extends RowData>(tableOptions: () => Omit<TableOptions<TFeatures, TData>, 'features'>) => AppAngularTable<TFeatures, TData, TTableComponents, TCellComponents, THeaderComponents>;
|
|
755
747
|
};
|
|
756
748
|
/**
|
|
757
749
|
* Creates app-scoped Angular table helpers with features, row models, and
|
|
@@ -765,7 +757,6 @@ type CreateTableHookResult<TFeatures extends TableFeatures, TTableComponents ext
|
|
|
765
757
|
* ```ts
|
|
766
758
|
* const { injectAppTable, createAppColumnHelper } = createTableHook({
|
|
767
759
|
* features,
|
|
768
|
-
* rowModels: {},
|
|
769
760
|
* tableComponents: {},
|
|
770
761
|
* cellComponents: {},
|
|
771
762
|
* headerComponents: {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/angular-table",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.43",
|
|
4
4
|
"description": "Headless UI for building powerful tables & datagrids for Angular.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"types": "./dist/types/tanstack-angular-table-static-functions.d.ts",
|
|
34
34
|
"default": "./dist/fesm2022/tanstack-angular-table-static-functions.mjs"
|
|
35
35
|
},
|
|
36
|
+
"./experimental-worker-plugin": {
|
|
37
|
+
"types": "./dist/types/tanstack-angular-table-experimental-worker-plugin.d.ts",
|
|
38
|
+
"default": "./dist/fesm2022/tanstack-angular-table-experimental-worker-plugin.mjs"
|
|
39
|
+
},
|
|
36
40
|
"./flex-render": {
|
|
37
41
|
"types": "./dist/types/tanstack-angular-table.d.ts",
|
|
38
42
|
"default": "./dist/fesm2022/tanstack-angular-table.mjs"
|
|
@@ -42,7 +46,7 @@
|
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"engines": {
|
|
45
|
-
"node": ">=
|
|
49
|
+
"node": ">=20"
|
|
46
50
|
},
|
|
47
51
|
"files": [
|
|
48
52
|
"dist",
|
|
@@ -52,14 +56,15 @@
|
|
|
52
56
|
],
|
|
53
57
|
"dependencies": {
|
|
54
58
|
"@tanstack/angular-store": "^0.11.0",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
59
|
+
"tslib": "^2.8.1",
|
|
60
|
+
"@tanstack/table-core": "9.0.0-beta.43"
|
|
57
61
|
},
|
|
58
62
|
"devDependencies": {
|
|
59
|
-
"@analogjs/vite-plugin-angular": "^2.6.
|
|
60
|
-
"@analogjs/vitest-angular": "^2.6.
|
|
61
|
-
"@angular/
|
|
62
|
-
"@angular/
|
|
63
|
+
"@analogjs/vite-plugin-angular": "^2.6.1",
|
|
64
|
+
"@analogjs/vitest-angular": "^2.6.1",
|
|
65
|
+
"@angular/compiler": "^22.0.2",
|
|
66
|
+
"@angular/core": "^22.0.2",
|
|
67
|
+
"@angular/platform-browser": "^22.0.2",
|
|
63
68
|
"ng-packagr": "^22.0.0",
|
|
64
69
|
"typescript": "6.0.3"
|
|
65
70
|
},
|
|
@@ -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.43'
|
|
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.43'
|
|
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.43'
|
|
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.
|