This skill builds on @tanstack/table-core#core and @tanstack/table-core#table-features. Read them first for the headless model and explicit features.
Setup
import { Component, signal } from '@angular/core'
import { FlexRender, injectTable, tableFeatures } from '@tanstack/angular-table'
type Person = { name: string; age: number }
const features = tableFeatures({})
const columns = [
{ accessorKey: 'name', header: 'Name' },
{ accessorKey: 'age', header: 'Age' },
]
@Component({ selector: 'app-table', imports: [FlexRender], template: ` @for (row of table.getRowModel().rows; track row.id) { @for (cell of row.getAllCells(); track cell.id) { <ng-container *flexRenderCell="cell; let value">{{ value }} } }
Core Patterns
Keep static inputs outside the initializer
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.
Render each content kind correctly
Import FlexRender for *flexRender, *flexRenderCell, *flexRenderHeader, and *flexRenderFooter. Definitions may yield primitives, TemplateRef, component types, or flexRenderComponent(...); Table does not supply markup or CSS.
Common Mistakes
CRITICAL Calling injectTable outside DI
Wrong:
export function makeTable() {
return injectTable(() => ({ features, columns, data }))
}
Correct:
export class TableComponent {
readonly table = injectTable(() => ({ features, columns, data: this.data() }))
}
injectTable asserts an Angular injection context and registers lifecycle cleanup there.
Source: packages/angular-table/src/injectTable.ts
HIGH Reallocating static options reactively
Wrong:
injectTable(() => ({
features: tableFeatures({}),
columns: makeColumns(),
data: this.data(),
}))
Correct:
const features = tableFeatures({})
const columns = makeColumns()
injectTable(() => ({ features, columns, data: this.data() }))
Every signal change reruns the initializer; rebuilding static inputs invalidates memoized Table work.
Source: packages/angular-table/src/injectTable.ts
HIGH Treating a render function as a component
Wrong:
cell: () => flexRenderComponent(() => 'value')
Correct:
cell: () => 'value'
flexRenderComponent wraps an Angular component type; ordinary functions and primitives are handled directly by FlexRender.
Source: docs/framework/angular/guide/rendering.md
API Discovery
Inspect node_modules/@tanstack/angular-table/dist/types/ for the bundled public API; inspect optional feature APIs in installed @tanstack/table-core/dist/features/.