CtrlK
BlogDocsLog inGet started
Tessl Logo

create-table-hook

Share TanStack Ember Table v9 features, row-model slots, defaults, and inferred column helpers with createTableHook, createAppTable, createAppColumnHelper, and appFeatures. Load for recurring Ember table conventions, per-table overrides, or confusion with component/context registries from other adapters.

66

Quality

80%

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

SKILL.md
Quality
Evals
Security

This skill builds on @tanstack/table-core#core, getting-started, and table-state. Use an app factory when several tables share real features or defaults; keep a one-off table on useTable.

Setup

import Component from '@glimmer/component'
import { tracked } from '@glimmer/tracking'
import {
  createSortedRowModel,
  createTableHook,
  rowSortingFeature,
  sortFn_alphanumeric,
  tableFeatures,
} from '@tanstack/ember-table'

const features = tableFeatures({
  rowSortingFeature,
  sortedRowModel: createSortedRowModel(),
  sortFns: { alphanumeric: sortFn_alphanumeric },
})

export const { appFeatures, createAppColumnHelper, createAppTable } =
  createTableHook({
    features,
    enableSortingRemoval: false,
  })

type Person = { id: string; name: string }
const columnHelper = createAppColumnHelper<Person>()
const columns = columnHelper.columns([
  columnHelper.accessor('name', { header: 'Name' }),
])

export default class PeopleTable extends Component {
  @tracked data: Person[] = []

  table = createAppTable(() => ({
    columns,
    data: this.data,
  }))
}

Create the hook and column helpers at stable module scope. createAppTable preserves the useTable options thunk, so tracked reads such as this.data remain reactive. Do not pass features again at the table call site; the factory owns the feature set and binds it into column inference.

Composition Contract

  • Hook options supply stable shared features and default table options.
  • createAppColumnHelper<TData>() binds the feature type while inferring each row type.
  • createAppTable(() => options) merges shared defaults with table-specific options.
  • Table-specific options win over shared defaults, except that the factory remains the feature owner.
  • appFeatures exposes the exact registered feature set for helper types or reusable utilities.

Shared options intentionally exclude columns, data, and state. Keep model inputs and controlled state at each table call site; share conventions, not one mutable state object across unrelated tables.

Sharing rowSortingFeature, sortedRowModel, and sorting defaults gives every table sorting capability; it does not make their internal sorting state shared. The factory technically accepts a stable external atom in shared atoms, but that deliberately couples tables and their column IDs. Prefer independent state unless synchronized tables are the actual product behavior.

Render Normally

Ember's factory does not register AppTable, AppCell, AppHeader, context hooks, or reusable component registries. Continue rendering with FlexRenderCell, FlexRenderHeader, and FlexRenderFooter. Continue wrapping receiver-dependent v9 methods in Ember template helpers as described by getting-started.

Common Mistakes

HIGH Copying another adapter's component registry

Wrong: expect table.AppTable, useTableContext, or a tableComponents option from React, Solid, Svelte, or Lit examples.

Correct: use the normal Ember FlexRender components and pass the table through ordinary Ember composition when another component truly needs it.

The Ember hook shares features/defaults and type inference only.

HIGH Passing features per table

Wrong:

createAppTable(() => ({ features: otherFeatures, columns, data: this.data }))

Correct: define a separate app hook when a table needs a genuinely different feature set. createAppTable omits features from its call-site type.

HIGH Recreating the hook or columns with tracked updates

Wrong: call createTableHook, createAppColumnHelper, or columns(...) inside a component getter or the createAppTable thunk.

Correct: create them once at module scope and let the table thunk read only changing inputs.

MEDIUM Sharing controlled state as a default

The hook options omit state. Put state and matching on[State]Change callbacks in each createAppTable thunk so every table has one clear owner per slice. Use a shared external atom only when tables intentionally coordinate the same compatible slice.

MEDIUM Repeating manual feature generics

Use createAppColumnHelper<Person>(); do not thread typeof features through every column helper after the factory has already captured it.

API Discovery

Inspect node_modules/@tanstack/ember-table/declarations/create-table-hook.d.ts for the installed factory return shape, omitted options, and merge precedence. Inspect use-table.d.ts for thunk reactivity and node_modules/@tanstack/table-core/dist/features/<feature>/ for the shared feature APIs. Do not infer Ember component/context behavior from another adapter's createTableHook.

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.