@tanstack/angular-table 9.0.0-alpha.5 → 9.0.0-alpha.51

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 (59) hide show
  1. package/README.md +127 -0
  2. package/dist/README.md +127 -0
  3. package/dist/fesm2022/tanstack-angular-table-static-functions.mjs +6 -0
  4. package/dist/fesm2022/tanstack-angular-table-static-functions.mjs.map +1 -0
  5. package/dist/fesm2022/tanstack-angular-table.mjs +1357 -242
  6. package/dist/fesm2022/tanstack-angular-table.mjs.map +1 -1
  7. package/dist/types/tanstack-angular-table-static-functions.d.ts +1 -0
  8. package/dist/types/tanstack-angular-table.d.ts +793 -0
  9. package/package.json +39 -19
  10. package/skills/angular/angular-rendering-directives/SKILL.md +415 -0
  11. package/skills/angular/angular-rendering-directives/references/content-shapes.md +142 -0
  12. package/skills/angular/angular-rendering-directives/references/create-table-hook-registries.md +89 -0
  13. package/skills/angular/angular-rendering-directives/references/di-tokens.md +171 -0
  14. package/skills/angular/angular-rendering-directives/references/flex-render-component-options.md +64 -0
  15. package/skills/angular/client-to-server/SKILL.md +467 -0
  16. package/skills/angular/compose-with-tanstack-query/SKILL.md +482 -0
  17. package/skills/angular/compose-with-tanstack-store/SKILL.md +397 -0
  18. package/skills/angular/compose-with-tanstack-virtual/SKILL.md +400 -0
  19. package/skills/angular/getting-started/SKILL.md +496 -0
  20. package/skills/angular/getting-started/references/feature-row-model-mapping.md +48 -0
  21. package/skills/angular/migrate-v8-to-v9/SKILL.md +419 -0
  22. package/skills/angular/migrate-v8-to-v9/references/v8-to-v9-mapping.md +261 -0
  23. package/skills/angular/production-readiness/SKILL.md +469 -0
  24. package/skills/angular/table-state/SKILL.md +429 -0
  25. package/skills/angular/table-state/references/external-atoms-and-app-hook.md +152 -0
  26. package/src/flex-render/context.ts +14 -0
  27. package/src/flex-render/flags.ts +34 -0
  28. package/src/flex-render/flexRenderComponent.ts +288 -0
  29. package/src/flex-render/flexRenderComponentFactory.ts +251 -0
  30. package/src/flex-render/renderer.ts +393 -0
  31. package/src/flex-render/view.ts +226 -0
  32. package/src/flexRender.ts +124 -0
  33. package/src/helpers/cell.ts +104 -0
  34. package/src/helpers/createTableHook.ts +499 -0
  35. package/src/helpers/flexRenderCell.ts +136 -0
  36. package/src/helpers/header.ts +99 -0
  37. package/src/helpers/table.ts +85 -0
  38. package/src/index.ts +23 -70
  39. package/src/injectTable.ts +206 -0
  40. package/src/{lazy-signal-initializer.ts → lazySignalInitializer.ts} +2 -2
  41. package/src/reactivity.ts +147 -0
  42. package/static-functions/index.ts +1 -0
  43. package/static-functions/ng-package.json +6 -0
  44. package/dist/esm2022/flex-render.mjs +0 -150
  45. package/dist/esm2022/index.mjs +0 -48
  46. package/dist/esm2022/lazy-signal-initializer.mjs +0 -43
  47. package/dist/esm2022/proxy.mjs +0 -83
  48. package/dist/esm2022/tanstack-angular-table.mjs +0 -5
  49. package/dist/flex-render.d.ts +0 -31
  50. package/dist/index.d.ts +0 -5
  51. package/dist/lazy-signal-initializer.d.ts +0 -5
  52. package/dist/proxy.d.ts +0 -3
  53. package/src/__tests__/createAngularTable.test.ts +0 -95
  54. package/src/__tests__/flex-render.test.ts +0 -178
  55. package/src/__tests__/lazy-init.test.ts +0 -124
  56. package/src/__tests__/test-setup.ts +0 -12
  57. package/src/__tests__/test-utils.ts +0 -62
  58. package/src/flex-render.ts +0 -187
  59. package/src/proxy.ts +0 -97
@@ -0,0 +1,499 @@
1
+ import { createColumnHelper as coreCreateColumnHelper } from '@tanstack/table-core'
2
+ import { injectTable } from '../injectTable'
3
+ import { injectFlexRenderContext } from '../flexRender'
4
+ import { injectTableHeaderContext as _injectTableHeaderContext } from './header'
5
+ import { injectTableContext as _injectTableContext } from './table'
6
+ import { injectTableCellContext as _injectTableCellContext } from './cell'
7
+ import type { FlexRenderContent } from '../flexRender'
8
+ import type { AngularTable } from '../injectTable'
9
+ import type {
10
+ AccessorFn,
11
+ AccessorFnColumnDef,
12
+ AccessorKeyColumnDef,
13
+ Cell,
14
+ CellContext,
15
+ CellData,
16
+ Column,
17
+ ColumnDef,
18
+ DeepKeys,
19
+ DeepValue,
20
+ DisplayColumnDef,
21
+ GroupColumnDef,
22
+ Header,
23
+ HeaderContext,
24
+ IdentifiedColumnDef,
25
+ Row,
26
+ RowData,
27
+ Table,
28
+ TableFeature,
29
+ TableFeatures,
30
+ TableOptions,
31
+ TableState,
32
+ } from '@tanstack/table-core'
33
+ import type { Signal, Type } from '@angular/core'
34
+
35
+ export type RenderableComponent =
36
+ | Type<any>
37
+ | (<T extends NonNullable<unknown>>(props: T) => FlexRenderContent<T>)
38
+
39
+ // =============================================================================
40
+ // Enhanced Context Types with Pre-bound Components
41
+ // =============================================================================
42
+
43
+ /**
44
+ * Enhanced CellContext with pre-bound cell components.
45
+ * The `cell` property includes the registered cellComponents.
46
+ */
47
+ export type AppCellContext<
48
+ TFeatures extends TableFeatures,
49
+ TData extends RowData,
50
+ TValue extends CellData,
51
+ TCellComponents extends Record<string, RenderableComponent>,
52
+ > = {
53
+ cell: Cell<TFeatures, TData, TValue> &
54
+ TCellComponents & { FlexRender: () => unknown }
55
+ column: Column<TFeatures, TData, TValue>
56
+ getValue: CellContext<TFeatures, TData, TValue>['getValue']
57
+ renderValue: CellContext<TFeatures, TData, TValue>['renderValue']
58
+ row: Row<TFeatures, TData>
59
+ table: Table<TFeatures, TData>
60
+ }
61
+
62
+ /**
63
+ * Enhanced HeaderContext with pre-bound header components.
64
+ * The `header` property includes the registered headerComponents.
65
+ */
66
+ export type AppHeaderContext<
67
+ TFeatures extends TableFeatures,
68
+ TData extends RowData,
69
+ TValue extends CellData,
70
+ THeaderComponents extends Record<string, RenderableComponent>,
71
+ > = {
72
+ column: Column<TFeatures, TData, TValue>
73
+ header: Header<TFeatures, TData, TValue> &
74
+ THeaderComponents & { FlexRender: () => unknown }
75
+ table: Table<TFeatures, TData>
76
+ }
77
+
78
+ // =============================================================================
79
+ // Enhanced Column Definition Types
80
+ // =============================================================================
81
+
82
+ /**
83
+ * Template type for column definitions that can be a string or a function.
84
+ */
85
+ export type AppColumnDefTemplate<TProps extends object> =
86
+ | string
87
+ | ((props: TProps) => any)
88
+
89
+ /**
90
+ * Enhanced column definition base with pre-bound components in cell/header/footer contexts.
91
+ */
92
+ export type AppColumnDefBase<
93
+ TFeatures extends TableFeatures,
94
+ TData extends RowData,
95
+ TValue extends CellData,
96
+ TCellComponents extends Record<string, RenderableComponent>,
97
+ THeaderComponents extends Record<string, RenderableComponent>,
98
+ > = Omit<
99
+ IdentifiedColumnDef<TFeatures, TData, TValue>,
100
+ 'cell' | 'header' | 'footer'
101
+ > & {
102
+ cell?: AppColumnDefTemplate<
103
+ AppCellContext<TFeatures, TData, TValue, TCellComponents>
104
+ >
105
+ header?: AppColumnDefTemplate<
106
+ AppHeaderContext<TFeatures, TData, TValue, THeaderComponents>
107
+ >
108
+ footer?: AppColumnDefTemplate<
109
+ AppHeaderContext<TFeatures, TData, TValue, THeaderComponents>
110
+ >
111
+ }
112
+
113
+ /**
114
+ * Enhanced display column definition with pre-bound components.
115
+ */
116
+ export type AppDisplayColumnDef<
117
+ TFeatures extends TableFeatures,
118
+ TData extends RowData,
119
+ TCellComponents extends Record<string, RenderableComponent>,
120
+ THeaderComponents extends Record<string, RenderableComponent>,
121
+ > = Omit<
122
+ DisplayColumnDef<TFeatures, TData, unknown>,
123
+ 'cell' | 'header' | 'footer'
124
+ > & {
125
+ cell?: AppColumnDefTemplate<
126
+ AppCellContext<TFeatures, TData, unknown, TCellComponents>
127
+ >
128
+ header?: AppColumnDefTemplate<
129
+ AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>
130
+ >
131
+ footer?: AppColumnDefTemplate<
132
+ AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>
133
+ >
134
+ }
135
+
136
+ /**
137
+ * Enhanced group column definition with pre-bound components.
138
+ */
139
+ export type AppGroupColumnDef<
140
+ TFeatures extends TableFeatures,
141
+ TData extends RowData,
142
+ TCellComponents extends Record<string, RenderableComponent>,
143
+ THeaderComponents extends Record<string, RenderableComponent>,
144
+ > = Omit<
145
+ GroupColumnDef<TFeatures, TData, unknown>,
146
+ 'cell' | 'header' | 'footer' | 'columns'
147
+ > & {
148
+ cell?: AppColumnDefTemplate<
149
+ AppCellContext<TFeatures, TData, unknown, TCellComponents>
150
+ >
151
+ header?: AppColumnDefTemplate<
152
+ AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>
153
+ >
154
+ footer?: AppColumnDefTemplate<
155
+ AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>
156
+ >
157
+ columns?: ReadonlyArray<ColumnDef<TFeatures, TData, unknown>>
158
+ }
159
+
160
+ // =============================================================================
161
+ // Enhanced Column Helper Type
162
+ // =============================================================================
163
+
164
+ /**
165
+ * Enhanced column helper with pre-bound components in cell/header/footer contexts.
166
+ * This enables TypeScript to know about the registered components when defining columns.
167
+ */
168
+ export type AppColumnHelper<
169
+ TFeatures extends TableFeatures,
170
+ TData extends RowData,
171
+ TCellComponents extends Record<string, RenderableComponent>,
172
+ THeaderComponents extends Record<string, RenderableComponent>,
173
+ > = {
174
+ /**
175
+ * Creates a data column definition with an accessor key or function.
176
+ * The cell, header, and footer contexts include pre-bound components.
177
+ */
178
+ accessor: <
179
+ TAccessor extends AccessorFn<TData> | DeepKeys<TData>,
180
+ TValue extends TAccessor extends AccessorFn<TData, infer TReturn>
181
+ ? TReturn
182
+ : TAccessor extends DeepKeys<TData>
183
+ ? DeepValue<TData, TAccessor>
184
+ : never,
185
+ >(
186
+ accessor: TAccessor,
187
+ column: TAccessor extends AccessorFn<TData>
188
+ ? AppColumnDefBase<
189
+ TFeatures,
190
+ TData,
191
+ TValue,
192
+ TCellComponents,
193
+ THeaderComponents
194
+ > & { id: string }
195
+ : AppColumnDefBase<
196
+ TFeatures,
197
+ TData,
198
+ TValue,
199
+ TCellComponents,
200
+ THeaderComponents
201
+ >,
202
+ ) => TAccessor extends AccessorFn<TData>
203
+ ? AccessorFnColumnDef<TFeatures, TData, TValue>
204
+ : AccessorKeyColumnDef<TFeatures, TData, TValue>
205
+
206
+ /**
207
+ * Wraps an array of column definitions to preserve each column's individual TValue type.
208
+ */
209
+ columns: <TColumns extends ReadonlyArray<ColumnDef<TFeatures, TData, any>>>(
210
+ columns: [...TColumns],
211
+ ) => Array<ColumnDef<TFeatures, TData, any>> & [...TColumns]
212
+
213
+ /**
214
+ * Creates a display column definition for non-data columns.
215
+ * The cell, header, and footer contexts include pre-bound components.
216
+ */
217
+ display: (
218
+ column: AppDisplayColumnDef<
219
+ TFeatures,
220
+ TData,
221
+ TCellComponents,
222
+ THeaderComponents
223
+ >,
224
+ ) => DisplayColumnDef<TFeatures, TData, unknown>
225
+
226
+ /**
227
+ * Creates a group column definition with nested child columns.
228
+ * The cell, header, and footer contexts include pre-bound components.
229
+ */
230
+ group: (
231
+ column: AppGroupColumnDef<
232
+ TFeatures,
233
+ TData,
234
+ TCellComponents,
235
+ THeaderComponents
236
+ >,
237
+ ) => GroupColumnDef<TFeatures, TData, unknown>
238
+ }
239
+
240
+ /**
241
+ * Extended table API returned by useAppTable with all App wrapper components
242
+ */
243
+ export type AppAngularTable<
244
+ TFeatures extends TableFeatures,
245
+ TData extends RowData,
246
+ TTableComponents extends Record<string, RenderableComponent>,
247
+ TCellComponents extends Record<string, RenderableComponent>,
248
+ THeaderComponents extends Record<string, RenderableComponent>,
249
+ > = AngularTable<TFeatures, TData> &
250
+ NoInfer<TTableComponents> & {
251
+ appCell: <TValue>(
252
+ cell: Cell<TFeatures, TData, TValue>,
253
+ ) => Cell<TFeatures, TData, TValue> & NoInfer<TCellComponents>
254
+
255
+ appHeader: <TValue>(
256
+ header: Header<TFeatures, TData, TValue>,
257
+ ) => Header<TFeatures, TData, TValue> & NoInfer<THeaderComponents>
258
+
259
+ appFooter: <TValue>(
260
+ footer: Header<TFeatures, TData, TValue>,
261
+ ) => Header<TFeatures, TData, TValue> & NoInfer<THeaderComponents>
262
+ }
263
+
264
+ // =============================================================================
265
+ // CreateTableHook Options and Props
266
+ // =============================================================================
267
+
268
+ /**
269
+ * Options for creating a table hook with pre-bound components and default table options.
270
+ * Extends all TableOptions except 'columns' | 'data' | 'store' | 'state' | 'initialState'.
271
+ */
272
+ export type CreateTableContextOptions<
273
+ TFeatures extends TableFeatures,
274
+ TTableComponents extends Record<string, RenderableComponent>,
275
+ TCellComponents extends Record<string, RenderableComponent>,
276
+ THeaderComponents extends Record<string, RenderableComponent>,
277
+ > = Omit<
278
+ TableOptions<TFeatures, any>,
279
+ 'columns' | 'data' | 'store' | 'state' | 'initialState'
280
+ > & {
281
+ /**
282
+ * Table-level components that need access to the table instance.
283
+ * These are available directly on the table object returned by useAppTable.
284
+ * Use `useTableContext()` inside these components.
285
+ * @example { PaginationControls, GlobalFilter, RowCount }
286
+ */
287
+ tableComponents?: TTableComponents
288
+ /**
289
+ * Cell-level components that need access to the cell instance.
290
+ * These are available on the cell object passed to AppCell's children.
291
+ * Use `useCellContext()` inside these components.
292
+ * @example { TextCell, NumberCell, DateCell, CurrencyCell }
293
+ */
294
+ cellComponents?: TCellComponents
295
+ /**
296
+ * Header-level components that need access to the header instance.
297
+ * These are available on the header object passed to AppHeader/AppFooter's children.
298
+ * Use `useHeaderContext()` inside these components.
299
+ * @example { SortIndicator, ColumnFilter, ResizeHandle }
300
+ */
301
+ headerComponents?: THeaderComponents
302
+ }
303
+
304
+ export type CreateTableHookResult<
305
+ TFeatures extends TableFeatures,
306
+ TTableComponents extends Record<string, RenderableComponent>,
307
+ TCellComponents extends Record<string, RenderableComponent>,
308
+ THeaderComponents extends Record<string, RenderableComponent>,
309
+ > = {
310
+ createAppColumnHelper: <TData extends RowData>() => AppColumnHelper<
311
+ TFeatures,
312
+ TData,
313
+ TCellComponents,
314
+ THeaderComponents
315
+ >
316
+ injectTableContext: <TData extends RowData = RowData>() => Signal<
317
+ AngularTable<TFeatures, TData>
318
+ >
319
+ injectTableHeaderContext: <
320
+ TValue extends CellData = CellData,
321
+ TRowData extends RowData = RowData,
322
+ >() => Signal<Header<TFeatures, TRowData, TValue>>
323
+ injectTableCellContext: <
324
+ TValue extends CellData = CellData,
325
+ TRowData extends RowData = RowData,
326
+ >() => Signal<Cell<TFeatures, TRowData, TValue>>
327
+ injectFlexRenderHeaderContext: <
328
+ TData extends RowData,
329
+ TValue extends CellData,
330
+ >() => HeaderContext<TFeatures, TData, TValue>
331
+ injectFlexRenderCellContext: <
332
+ TData extends RowData,
333
+ TValue extends CellData,
334
+ >() => CellContext<TFeatures, TData, TValue>
335
+ injectAppTable: <TData extends RowData>(
336
+ tableOptions: () => Omit<
337
+ TableOptions<TFeatures, TData>,
338
+ '_features' | '_rowModels'
339
+ >,
340
+ ) => AppAngularTable<
341
+ TFeatures,
342
+ TData,
343
+ TTableComponents,
344
+ TCellComponents,
345
+ THeaderComponents
346
+ >
347
+ }
348
+
349
+ /**
350
+ * Creates app-scoped Angular table helpers with features, row models, and
351
+ * renderable component maps pre-bound.
352
+ *
353
+ * Use this when an app or design system wants typed `injectAppTable`,
354
+ * pre-bound column helpers, and typed table/cell/header context injection
355
+ * helpers without repeating the same feature and component generics.
356
+ *
357
+ * @example
358
+ * ```ts
359
+ * const { injectAppTable, createAppColumnHelper } = createTableHook({
360
+ * _features,
361
+ * _rowModels: {},
362
+ * tableComponents: {},
363
+ * cellComponents: {},
364
+ * headerComponents: {},
365
+ * })
366
+ * ```
367
+ */
368
+ export function createTableHook<
369
+ TFeatures extends TableFeatures,
370
+ const TTableComponents extends Record<string, RenderableComponent>,
371
+ const TCellComponents extends Record<string, RenderableComponent>,
372
+ const THeaderComponents extends Record<string, RenderableComponent>,
373
+ >({
374
+ tableComponents,
375
+ cellComponents,
376
+ headerComponents,
377
+ ...defaultTableOptions
378
+ }: CreateTableContextOptions<
379
+ TFeatures,
380
+ TTableComponents,
381
+ TCellComponents,
382
+ THeaderComponents
383
+ >): CreateTableHookResult<
384
+ TFeatures,
385
+ TTableComponents,
386
+ TCellComponents,
387
+ THeaderComponents
388
+ > {
389
+ function injectTableContext<TData extends RowData = RowData>(): Signal<
390
+ AngularTable<TFeatures, TData>
391
+ > {
392
+ return _injectTableContext<TFeatures, TData>()
393
+ }
394
+
395
+ function injectTableHeaderContext<
396
+ TValue extends CellData = CellData,
397
+ TRowData extends RowData = RowData,
398
+ >(): Signal<Header<TFeatures, TRowData, TValue>> {
399
+ return _injectTableHeaderContext<TFeatures, TRowData, TValue>()
400
+ }
401
+
402
+ function injectTableCellContext<
403
+ TValue extends CellData = CellData,
404
+ TRowData extends RowData = RowData,
405
+ >(): Signal<Cell<TFeatures, TRowData, TValue>> {
406
+ return _injectTableCellContext<TFeatures, TRowData, TValue>()
407
+ }
408
+
409
+ function injectFlexRenderHeaderContext<
410
+ TData extends RowData,
411
+ TValue extends CellData,
412
+ >(): HeaderContext<TFeatures, TData, TValue> {
413
+ return injectFlexRenderContext<HeaderContext<TFeatures, TData, TValue>>()
414
+ }
415
+
416
+ function injectFlexRenderCellContext<
417
+ TData extends RowData,
418
+ TValue extends CellData,
419
+ >(): CellContext<TFeatures, TData, TValue> {
420
+ return injectFlexRenderContext<CellContext<TFeatures, TData, TValue>>()
421
+ }
422
+
423
+ function injectAppTable<
424
+ TData extends RowData,
425
+ TSelected = TableState<TFeatures>,
426
+ >(
427
+ tableOptions: () => Omit<
428
+ TableOptions<TFeatures, TData>,
429
+ '_features' | '_rowModels'
430
+ >,
431
+ ): AppAngularTable<
432
+ TFeatures,
433
+ TData,
434
+ TTableComponents,
435
+ TCellComponents,
436
+ THeaderComponents
437
+ > {
438
+ function appCell(cell: Cell<TFeatures, TData, any>) {
439
+ return cell as Cell<TFeatures, TData, any> & TCellComponents
440
+ }
441
+
442
+ function appHeader(header: Header<TFeatures, TData, any>) {
443
+ return header as Header<TFeatures, TData, any> & THeaderComponents
444
+ }
445
+
446
+ function appFooter(footer: Header<TFeatures, TData, any>) {
447
+ return footer as Header<TFeatures, TData, any> & THeaderComponents
448
+ }
449
+
450
+ const appTableFeatures: TableFeature<{}> = {
451
+ constructTableAPIs: (table) => {
452
+ Object.assign(table, tableComponents, { appCell, appHeader, appFooter })
453
+ },
454
+ assignCellPrototype(prototype) {
455
+ Object.assign(prototype, cellComponents)
456
+ },
457
+ assignHeaderPrototype(prototype) {
458
+ Object.assign(prototype, headerComponents)
459
+ },
460
+ }
461
+
462
+ return injectTable<TFeatures, TData>(() => {
463
+ return {
464
+ ...defaultTableOptions,
465
+ ...tableOptions(),
466
+ _features: {
467
+ ...defaultTableOptions._features,
468
+ appTableFeatures,
469
+ },
470
+ } as TableOptions<TFeatures, TData>
471
+ }) as AngularTable<any, any>
472
+ }
473
+
474
+ function createAppColumnHelper<TData extends RowData>(): AppColumnHelper<
475
+ TFeatures,
476
+ TData,
477
+ TCellComponents,
478
+ THeaderComponents
479
+ > {
480
+ // The runtime implementation is the same - components are attached at render time
481
+ // This cast provides the enhanced types for column definitions
482
+ return coreCreateColumnHelper<TFeatures, TData>() as AppColumnHelper<
483
+ TFeatures,
484
+ TData,
485
+ TCellComponents,
486
+ THeaderComponents
487
+ >
488
+ }
489
+
490
+ return {
491
+ createAppColumnHelper,
492
+ injectTableContext,
493
+ injectTableHeaderContext,
494
+ injectTableCellContext,
495
+ injectFlexRenderHeaderContext,
496
+ injectFlexRenderCellContext,
497
+ injectAppTable,
498
+ }
499
+ }
@@ -0,0 +1,136 @@
1
+ import {
2
+ DestroyRef,
3
+ Directive,
4
+ Injector,
5
+ TemplateRef,
6
+ ViewContainerRef,
7
+ computed,
8
+ inject,
9
+ input,
10
+ } from '@angular/core'
11
+ import {
12
+ Cell,
13
+ CellData,
14
+ Header,
15
+ RowData,
16
+ TableFeatures,
17
+ } from '@tanstack/table-core'
18
+ import { FlexViewRenderer } from '../flex-render/renderer'
19
+ import type { FlexRenderInputContent } from '../flex-render/renderer'
20
+ import type { CellContext, HeaderContext } from '@tanstack/table-core'
21
+
22
+ /**
23
+ * Simplified directive wrapper of `*flexRender`.
24
+ *
25
+ * Use this utility component to render headers, cells, or footers with custom markup.
26
+ *
27
+ * Only one prop (`cell`, `header`, or `footer`) may be passed based on the used selector.
28
+ *
29
+ * @example
30
+ * ```html
31
+ * <td *flexRenderCell="cell; let cell">{{cell}}</td>
32
+ * <th *flexRenderHeader="header; let header">{{header}}</th>
33
+ * <th *flexRenderFooter="footer; let footer">{{footer}}</th>
34
+ * ```
35
+ *
36
+ * This replaces calling `*flexRender` directly like this:
37
+ * ```html
38
+ * <td *flexRender="cell.column.columnDef.cell; props: cell.getContext(); let cell">{{cell}}</td>
39
+ * <td *flexRender="header.column.columnDef.header; props: header.getContext(); let header">{{header}}</td>
40
+ * <td *flexRender="footer.column.columnDef.footer; props: footer.getContext(); let footer">{{footer}}</td>
41
+ * ```
42
+ *
43
+ * Can be imported through {@link FlexRenderCell} or {@link FlexRender} import,
44
+ * which the latter is preferred.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import {FlexRender} from '@tanstack/angular-table
49
+ *
50
+ * @Component({
51
+ * // ...
52
+ * imports: [
53
+ * FlexRender
54
+ * ]
55
+ * })
56
+ * ```
57
+ */
58
+ @Directive({
59
+ selector:
60
+ 'ng-template[flexRenderCell], ng-template[flexRenderFooter], ng-template[flexRenderHeader]',
61
+ })
62
+ export class FlexRenderCell<
63
+ TFeatures extends TableFeatures,
64
+ TData extends RowData,
65
+ TValue extends CellData,
66
+ > {
67
+ readonly cell = input<Cell<TFeatures, TData, TValue>>(undefined, {
68
+ alias: 'flexRenderCell',
69
+ })
70
+
71
+ readonly header = input<Header<TFeatures, TData, TValue>>(undefined, {
72
+ alias: 'flexRenderHeader',
73
+ })
74
+
75
+ readonly footer = input<Header<TFeatures, TData, TValue>>(undefined, {
76
+ alias: 'flexRenderFooter',
77
+ })
78
+
79
+ readonly #renderData = computed<
80
+ | [
81
+ content: FlexRenderInputContent<CellContext<TFeatures, TData, TValue>>,
82
+ props: CellContext<TFeatures, TData, TValue>,
83
+ ]
84
+ | [
85
+ content: FlexRenderInputContent<
86
+ HeaderContext<TFeatures, TData, TValue>
87
+ >,
88
+ props: HeaderContext<TFeatures, TData, TValue>,
89
+ ]
90
+ | [content: null, props: null]
91
+ >(
92
+ () => {
93
+ const cell = this.cell()
94
+ const header = this.header()
95
+ const footer = this.footer()
96
+ if (cell) {
97
+ return [cell.column.columnDef.cell, cell.getContext()]
98
+ }
99
+ if (header) {
100
+ return [header.column.columnDef.header, header.getContext()]
101
+ }
102
+ if (footer) {
103
+ return [footer.column.columnDef.footer, footer.getContext()]
104
+ }
105
+ return [null, null]
106
+ },
107
+ {
108
+ equal: (a, b) => {
109
+ return a[0] === b[0] && a[1] === b[1]
110
+ },
111
+ },
112
+ )
113
+
114
+ readonly #injector = inject(Injector)
115
+ readonly #templateRef = inject(TemplateRef)
116
+ readonly #viewContainerRef = inject(ViewContainerRef)
117
+
118
+ constructor() {
119
+ const content = computed(() => this.#renderData()[0])
120
+ const props = computed(() => this.#renderData()[1])
121
+
122
+ const renderer = new FlexViewRenderer<TFeatures, TData, TValue, any>({
123
+ content: content,
124
+ props: props,
125
+ injector: () => this.#injector,
126
+ templateRef: this.#templateRef,
127
+ viewContainerRef: this.#viewContainerRef,
128
+ })
129
+
130
+ renderer.mount()
131
+
132
+ inject(DestroyRef).onDestroy(() => {
133
+ renderer.destroy()
134
+ })
135
+ }
136
+ }