# How TanStack Table Integration Facilitates Data Table Creation in Celeris Web

> Discover how TanStack Table integration in Celeris Web simplifies data table creation. Learn about its type-safe API, column helpers, and composable instances for efficient grid building.

- Repository: [Kirk Lin/celeris-web](https://github.com/kirklin/celeris-web)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Celeris Web leverages TanStack Vue-Table to provide a type-safe, declarative API for building data grids through column helpers, composable table instances, and a generic rendering component that supports features like pagination via pluggable row models.**

Celeris Web, the Vue 3 admin dashboard framework in the `kirklin/celeris-web` repository, integrates TanStack Vue-Table to handle complex data table requirements without repetitive UI code. This TanStack Table integration allows developers to define typed columns declaratively, instantiate tables through the `useVueTable` composable, and render any data shape using a single generic `AppTable` component.

## Declarative Column Definitions with createColumnHelper

The integration starts with defining column schemas using TanStack's `createColumnHelper<T>()` utility. This helper generates type-safe column definitions that map row properties to renderable headers and cells.

In [`apps/admin/src/pages/components/headless-table/basic/index.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/pages/components/headless-table/basic/index.vue), columns are constructed by invoking helper methods that specify accessors, headers, and cell renderers:

```typescript
const columnHelper = createColumnHelper<ChatGPTDemoTableRow>();
const columns = [
  columnHelper.accessor(row => row.userInput, { 
    id: "userInput", 
    header: () => "用户输入",
    // additional metadata...
  }),
  // additional columns...
];

```

Each column definition encapsulates:
- **Accessor functions** that extract values from row objects
- **Header renderers** that return the column title
- **Cell renderers** that format the display value
- **Unique identifiers** for state tracking

## Building the Table Instance with useVueTable

After defining columns, developers create a reactive table instance using `useVueTable`. This composable accepts the column array, a data source, and row-model plugins that determine available features.

The basic implementation in [`apps/admin/src/pages/components/headless-table/basic/index.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/pages/components/headless-table/basic/index.vue) configures the core row model:

```typescript
const table = useVueTable({
  get data() { return chatGPTDemoTestData; },
  columns,
  getCoreRowModel: getCoreRowModel(),
});

```

To add pagination, the [`apps/admin/src/pages/components/headless-table/pagination/index.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/pages/components/headless-table/pagination/index.vue) example injects an additional row model:

```typescript
const table = useVueTable({
  get data() { return largeDataSet; },
  columns,
  getCoreRowModel: getCoreRowModel(),
  getPaginationRowModel: getPaginationRowModel(),
});

```

**Key row model options include:**
- `getCoreRowModel()` – Computes the basic row/column matrix required for all tables
- `getPaginationRowModel()` – Enables page slicing and navigation state
- `getSortedRowModel()` – Adds column sorting capabilities
- `getFilteredRowModel()` – Supports global and column-specific filtering

## Generic Rendering with the AppTable Component

Celeris Web abstracts the rendering logic into a reusable `AppTable` component located at [`apps/admin/src/component/AppTable/src/AppTable.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/component/AppTable/src/AppTable.vue). This component accepts a generic `Table<T>` prop and delegates header and cell rendering to TanStack's `<FlexRender>` component.

The component iterates over table state methods to build the UI structure:

```vue
<NTable>
  <thead>
    <tr v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
      <th v-for="header in headerGroup.headers" :key="header.id">
        <FlexRender 
          :render="header.column.columnDef.header" 
          :props="header.getContext()" 
        />
      </th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="row in table.getRowModel().rows" :key="row.id">
      <td v-for="cell in row.getVisibleCells()" :key="cell.id">
        <FlexRender 
          :render="cell.column.columnDef.cell" 
          :props="cell.getContext()" 
        />
      </td>
    </tr>
  </tbody>
</NTable>

```

The TypeScript signature ensures type safety across any data shape:

```typescript
defineProps<{ table: Table<T>; }>();

```

This architecture separates data logic from presentation, allowing the same UI component to render user tables, transaction logs, or inventory lists without modification.

## Adding Advanced Features via Row Models

The pluggable row-model system enables sophisticated features through configuration rather than component rewriting. By including additional getters in the `useVueTable` options object, the `AppTable` component automatically gains functionality.

**To implement pagination:**
1. Import `getPaginationRowModel` from `@tanstack/vue-table`
2. Include it in the table configuration
3. Access pagination state via `table.getState().pagination` and navigation methods like `table.previousPage()`

**To enable sorting:**
1. Add `getSortedRowModel()` to the configuration
2. Configure sortable columns in the column definitions
3. Toggle sorting through `header.column.getToggleSortingHandler()`

Because these features operate at the data-model level within TanStack Vue-Table, the rendering code in [`AppTable.vue`](https://github.com/kirklin/celeris-web/blob/main/AppTable.vue) remains unchanged regardless of which features are active.

## Summary

- **Type-safe columns**: `createColumnHelper<T>()` generates strongly typed column definitions that link row data to render functions.
- **Composable state**: `useVueTable` creates reactive table instances that manage row models, pagination, and sorting state independently of the UI layer.
- **Generic rendering**: The `AppTable` component in [`apps/admin/src/component/AppTable/src/AppTable.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/component/AppTable/src/AppTable.vue) uses `<FlexRender>` to display any `Table<T>` instance without prop drilling or conditional rendering logic.
- **Feature plugins**: Advanced capabilities like pagination (`getPaginationRowModel`) are enabled by adding row-model getters to the table configuration, keeping the component surface area minimal.

## Frequently Asked Questions

### How does Celeris Web handle type safety in TanStack Table columns?

Celeris Web uses `createColumnHelper<T>()` to maintain end-to-end type safety from the row data structure through to the cell renderers. When defining columns in files like [`apps/admin/src/pages/components/headless-table/basic/index.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/pages/components/headless-table/basic/index.vue), the generic type parameter ensures that accessor functions and cell context values are properly typed, preventing runtime errors from mismatched property access.

### What is the role of FlexRender in the AppTable component?

`<FlexRender>` is TanStack Vue-Table's rendering utility that invokes the `header` and `cell` functions defined in column configurations. In [`apps/admin/src/component/AppTable/src/AppTable.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/component/AppTable/src/AppTable.vue), it receives the render function from the column definition and the context object (containing row data, column state, and table instance), executing the appropriate Vue render function to produce the final DOM output.

### Can I add sorting and filtering without modifying the AppTable component?

Yes. According to the source code patterns in [`apps/admin/src/pages/components/headless-table/pagination/index.vue`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/pages/components/headless-table/pagination/index.vue), features like sorting and filtering are enabled by importing the corresponding row-model plugins (e.g., `getSortedRowModel`, `getFilteredRowModel`) and passing them to `useVueTable`. The `AppTable` component automatically adapts to these features because it reads from the standard `table.getRowModel()` and `table.getHeaderGroups()` APIs regardless of which plugins are active.

### Where is the TanStack Vue-Table dependency declared in the repository?

The dependency is declared in [`pnpm-workspace.yaml`](https://github.com/kirklin/celeris-web/blob/main/pnpm-workspace.yaml) as `@tanstack/vue-table` version `^8.21.3`, making it available throughout the Celeris Web monorepo for use in admin components and page implementations.