Angular's structural-directive rendering pipeline for TanStack Table v9. Covers `FlexRender` (`*flexRender`), the shorthand directives `*flexRenderCell` / `*flexRenderHeader` / `*flexRenderFooter`, the `flexRenderComponent(Component, { inputs, outputs, bindings, directives, injector })` wrapper, DI tokens `TanStackTableToken` / `TanStackTableHeaderToken` / `TanStackTableCellToken` with their `injectTableContext()` / `injectTableHeaderContext()` / `injectTableCellContext()` helpers, the `[tanStackTable]` / `[tanStackTableHeader]` / `[tanStackTableCell]` host directives, `injectFlexRenderContext()`, automatic token injection inside `*flexRender`, and the four content shapes (primitive, `TemplateRef`, component type, `flexRenderComponent` wrapper).
Convert an Angular Table v9 from client-side to server-side processing. Flip `manualPagination` / `manualSorting` / `manualFiltering` / `manualGrouping` / `manualExpanding` for the slices the server now owns; drop the corresponding `_rowModels` row-model factories the server replaces; supply `rowCount` (server total) so pagination computes correctly; hoist `pagination` / `sorting` / `columnFilters` / `globalFilter` to Angular signals with `state` + `on[State]Change`; fetch via `rxResource` / `httpResource` / `@tanstack/angular-query`; preserve previous data on refetch with `linkedSignal` (or `placeholderData: keepPreviousData` for Query); set `getRowId` for stable selection across refetches.
Compose TanStack Table v9 with `@tanstack/angular-query-experimental` for server-side data. Key the query on the controlled table state that drives the request (pagination, sorting, filters); use `placeholderData: keepPreviousData` to avoid a "0 rows flash" between pages; set `manualPagination` / `manualSorting` / `manualFiltering` for the slices the server owns; drop the matching client `_rowModels` factories; pass `rowCount` from the server response; set `getRowId` for stable selection across refetches; hoist controlled slices to Angular signals + `state` + `on[State]Change`. Alternative — `rxResource` / `httpResource` if you don't want to add the Query dependency (see `client-to-server`).
Compose TanStack Table v9 with `@tanstack/angular-store`. TanStack Table v9 is itself built on TanStack Store — each state slice is an atom. Three read surfaces: `table.atoms.<slice>` (per-slice readonly, signal-backed), `table.store` (flat readonly view), and `table.baseAtoms.<slice>` (writable). The `atoms` table option lets you replace an internal slice with an external TanStack Store atom for cross-app sharing (URL sync, persistence, multi-table coordination). In Angular, native signals + `state` + `on[State]Change` is the default; reach for external atoms only when ownership crosses an app boundary the signal model can't easily span.
Compose TanStack Table v9 with `@tanstack/angular-virtual` for virtualized rendering of large row sets. TanStack Table does NOT virtualize on its own. Pattern: get `rows = table.getRowModel().rows`, feed `rows.length` to `injectVirtualizer({ count, estimateSize, getScrollElement, overscan })`, iterate `virtualizer.getVirtualItems()` in the template, position each row with `transform: translateY(item.start)` inside a tall sentinel, set `[style.height.px]="virtualizer.getTotalSize()"` to make the scrollbar correct. Handle the table-feature interactions: row-expanding (variable subRow heights → measure with `measureElement`), column sizing/pinning (column virtualization is separate), row-selection (selection state survives virtualization because it's keyed by row ID).
End-to-end first-table journey for TanStack Table v9 in Angular: install `@tanstack/angular-table`, declare `_features` with `tableFeatures()`, register row-model factories under `_rowModels` with explicit `*Fns` parameters, build columns with the `TFeatures, TData` generic order, call `injectTable(() => ({...}))` from an injection context, and render with `FlexRender` / `*flexRenderHeader` / `*flexRenderCell` / `*flexRenderFooter`. Covers the minimum-viable signal-backed table plus the upgrade path to sorting + filtering + pagination.
Mechanical v8 → v9 migration for `@tanstack/angular-table`: `createAngularTable` → `injectTable`, `get*RowModel()` options → `_rowModels` factories with explicit `*Fns`, required `_features` via `tableFeatures()`, `state` access via `table.store.state` instead of `table.getState()`, `createColumnHelper<TFeatures, TData>()` generic-order flip, every type now requires `TFeatures`, `enablePinning` split into `enableColumnPinning` / `enableRowPinning`, `sortingFn` → `sortFn` rename pile, `ColumnSizingInfo` → `ColumnResizing` split, removal of `_`-prefixed internals, signal-backed atoms replacing v8 memoized accessors, and structural-directive rendering replacing v8 component-based rendering.
Ship-ready optimizations for Angular Table v9: register only the `_features` you actually use (tree-shake the bundle); keep `columns` / `_features` / `_rowModels` / feature-fn maps as stable references OUTSIDE the `injectTable` initializer; pass only the `*Fns` your data needs to `createSortedRowModel` / `createFilteredRowModel` / `createGroupedRowModel`; use `ChangeDetectionStrategy.OnPush`; lean on signal-backed atoms (`table.atoms.<slice>.get()`) instead of broad `table.store.state` reads where granularity matters; use `{ equal: shallow }` on object/array `computed` selectors; set `getRowId` for stable identity; track by `id` in every `@for`; defer cell components with `flexRenderComponent` only when you need its options; scope DI tokens via `[tanStackTable*]` directives to kill prop drilling.