CtrlK
BlogDocsLog inGet started
Tessl Logo

table-state

Use Angular-signal-backed table.atoms, direct template reads, computed selectors, controlled signals, value-or-updater callbacks, and external Angular Store atoms while accounting for injectTable initializer reruns.

60

Quality

71%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Fix and improve this skill with Tessl

tessl review fix ./packages/angular-table/skills/table-state/SKILL.md
SKILL.md
Quality
Evals
Security

This skill builds on @tanstack/table-core#core and getting-started. Read them first for state ownership and Angular construction.

State Mental Model

TanStack Table is primarily a state coordinator. Keep state internal unless another system must read, persist, or drive it. Without initialState, atoms, state, or on[State]Change, the table owns all registered slices.

  • table.baseAtoms are internal writable atoms initialized from resolved initial state.
  • table.atoms are readonly derived atoms for the active owner of each registered slice.
  • table.store combines those atoms into one readonly flat store.

The Angular adapter backs atoms with Angular signals. Reads participate in tracking inside templates, computed, and effect; signal reads inside the injectTable initializer also rerun that initializer and call setOptions. State is feature-based: missing pagination state or APIs indicate a missing rowPaginationFeature. Hoist stable features and columns outside the initializer, and return signal-backed data without mapping or slicing inline.

Setup

import { computed, signal } from '@angular/core'
import {
  injectTable,
  rowPaginationFeature,
  tableFeatures,
} from '@tanstack/angular-table'

const features = tableFeatures({ rowPaginationFeature })
const columns = [{ accessorKey: 'name' }]

export class TableComponent {
  readonly data = signal([{ name: 'Ada' }])
  readonly table = injectTable(() => ({ features, columns, data: this.data() }))
  readonly pageIndex = computed(
    () => this.table.atoms.pagination.get().pageIndex,
  )
}

Angular-backed table atom reads are signal reads. Templates, computed, and effect track them directly.

Core Patterns

Prefer external atoms for cross-system state

import { createAtom } from '@tanstack/angular-store'
import type { PaginationState } from '@tanstack/angular-table'

readonly paginationAtom = createAtom<PaginationState>({ pageIndex: 0, pageSize: 20 })
readonly table = injectTable(() => ({
  features, columns, data: this.data(), atoms: { pagination: this.paginationAtom },
}))

The atom can feed Query without making every state write rerun the Table initializer.

Resolve controlled signal updaters

readonly pagination = signal({ pageIndex: 0, pageSize: 20 })
readonly table = injectTable(() => ({
  features, columns, data: this.data(), state: { pagination: this.pagination() },
  onPaginationChange: next => typeof next === 'function' ? this.pagination.update(next) : this.pagination.set(next),
}))

Choose State Ownership

Use one owner for each slice:

  • Prefer internal state and feature APIs for local interaction.
  • Use initialState for starting/reset values; later changes do not reset current state.
  • Prefer a stable atom from @tanstack/angular-store in atoms for Query or other cross-system state. Table APIs update it without a change callback.
  • Use an Angular signal read in state.<slice> plus the matching callback for simple controlled state. Handle raw values and updater functions.

External atoms win over controlled state, which syncs into the internal base atom. Do not give a slice two owners. The global v8 onStateChange option is gone; subscribe to table.store when all state changes must be observed.

Initialize, Update, and Reset

Prefer feature methods such as setSorting, nextPage, toggleVisibility, and toggleSelected. Direct base-atom writes are a rare escape hatch for internal state; write the external atom when it owns a slice.

this.table.resetSorting()
this.table.resetPagination()
this.table.resetPagination(true)

Feature resets use table.initialState unless true requests the feature default, and can update external owners. Core table.reset() resets internal base atoms only. Use feature-specific types such as PaginationState; use TableState<typeof features> when the complete registered state type is needed.

Common Mistakes

MEDIUM Wrapping atoms redundantly

Wrong:

readonly pagination = computed(() => computed(() => this.table.atoms.pagination.get())())

Correct:

readonly pagination = computed(() => this.table.atoms.pagination.get())

Table atoms already bridge to Angular signals; one tracked read is sufficient.

Source: docs/framework/angular/guide/table-state.md

HIGH Ignoring initializer reruns

Wrong:

injectTable(() => ({
  features: tableFeatures({ rowPaginationFeature }),
  columns: makeColumns(),
  state: { pagination: this.pagination() },
  data,
}))

Correct:

injectTable(() => ({
  features,
  columns,
  state: { pagination: this.pagination() },
  data,
}))

Controlled signal writes rerun the initializer, so static work must remain outside it.

Source: packages/angular-table/src/injectTable.ts

HIGH Storing updater functions

Wrong:

onPaginationChange: (next) => this.pagination.set(next)

Correct:

onPaginationChange: (next) =>
  typeof next === 'function'
    ? this.pagination.update(next)
    : this.pagination.set(next)

Callbacks receive a value or updater; assigning the function corrupts owned state.

Source: examples/angular/basic-external-state/src/app/app.ts

MEDIUM Giving one slice multiple owners

Wrong:

{ initialState: { pagination: start }, atoms: { pagination: this.paginationAtom } }

Correct:

{
  atoms: {
    pagination: this.paginationAtom
  }
}

External atoms/state override initial state; choose one owner for each slice.

Source: docs/framework/angular/guide/table-state.md

API Discovery

Inspect node_modules/@tanstack/angular-table/dist/types/ and reactivity.d.ts; inspect @tanstack/angular-store/dist/ for external atoms and installed core feature source for state APIs.

Repository
TanStack/table
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.