Skip to content

Commit 09ee20a

Browse files
Merge branch 'beta' into mh/grouping_fix
2 parents 4815227 + 19fa735 commit 09ee20a

576 files changed

Lines changed: 4371 additions & 3166 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/config.json

Lines changed: 52 additions & 58 deletions
Large diffs are not rendered by default.

docs/framework/angular/guide/column-faceting.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Want to skip to the implementation? Check out these Angular examples:
88

99
- [Faceted Filters](../examples/filters-faceted)
1010

11-
### Angular Setup
11+
### Faceting Setup
12+
13+
Here's how you set up your table to use faceting features. Adding the faceting feature enables the related APIs. Additionally, if using client-side faceting, you also need to set up `filteredRowModel` and `facetedRowModel` after their associated features because row model slots are type-checked.
1214

1315
```ts
1416
import { signal } from '@angular/core'
@@ -17,8 +19,8 @@ import { injectTable, tableFeatures, columnFacetingFeature, columnFilteringFeatu
1719
const features = tableFeatures({
1820
columnFacetingFeature,
1921
columnFilteringFeature,
20-
filteredRowModel: createFilteredRowModel(),
21-
facetedRowModel: createFacetedRowModel(),
22+
filteredRowModel: createFilteredRowModel(), // if using client-side filtering
23+
facetedRowModel: createFacetedRowModel(), // if using client-side faceting
2224
facetedUniqueValues: createFacetedUniqueValues(),
2325
facetedMinMaxValues: createFacetedMinMaxValues(),
2426
filterFns,

docs/framework/angular/guide/column-filtering.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ Want to skip to the implementation? Check out these Angular examples:
1010
- [Faceted Filters](../examples/filters-faceted)
1111
- [Fuzzy Search](../examples/filters-fuzzy)
1212

13-
### Angular Setup
13+
### Column Filtering Setup
14+
15+
Here's how you set up your table to use column filtering features. Adding the column filtering feature enables the related APIs. Additionally, if using client-side filtering, you also need to set up `filteredRowModel` after its associated feature because row model slots are type-checked.
1416

1517
```ts
1618
import { signal } from '@angular/core'
1719
import { injectTable, tableFeatures, columnFilteringFeature, createFilteredRowModel, filterFns } from '@tanstack/angular-table'
1820

1921
const features = tableFeatures({
2022
columnFilteringFeature,
21-
filteredRowModel: createFilteredRowModel(),
23+
filteredRowModel: createFilteredRowModel(), // if using client-side filtering
2224
filterFns,
2325
})
2426

docs/framework/angular/guide/column-ordering.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Want to skip to the implementation? Check out these Angular examples:
88

99
- [Column Ordering](../examples/column-ordering)
1010

11-
### Angular Setup
11+
### Column Ordering Setup
12+
13+
Here's how you set up your table to use column ordering features. Adding the column ordering feature enables the related APIs.
1214

1315
```ts
1416
import { signal } from '@angular/core'

docs/framework/angular/guide/column-pinning.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Want to skip to the implementation? Check out these Angular examples:
1010
- [Column Pinning Split](../examples/column-pinning-split)
1111
- [Sticky Column Pinning](../examples/column-pinning-sticky)
1212

13-
### Angular Setup
13+
### Column Pinning Setup
14+
15+
Here's how you set up your table to use column pinning features. Adding the column pinning feature enables the related APIs.
1416

1517
```ts
1618
import { signal } from '@angular/core'

docs/framework/angular/guide/column-resizing.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@ Want to skip to the implementation? Check out these Angular examples:
99
- [Column Resizing](../examples/column-resizing)
1010
- [Performant Column Resizing](../examples/column-resizing-performant)
1111

12-
### Angular Setup
12+
### Column Resizing Setup
13+
14+
Here's how you set up your table to use column resizing features. Column resizing depends on column sizing, so add `columnSizingFeature` before `columnResizingFeature`. Adding the column resizing feature enables the related APIs.
1315

1416
```ts
1517
import { signal } from '@angular/core'
16-
import { injectTable, tableFeatures, columnResizingFeature } from '@tanstack/angular-table'
18+
import { injectTable, tableFeatures, columnSizingFeature, columnResizingFeature } from '@tanstack/angular-table'
1719

18-
const features = tableFeatures({ columnResizingFeature })
20+
const features = tableFeatures({
21+
columnSizingFeature,
22+
columnResizingFeature,
23+
})
1924

2025
export class App {
2126
readonly data = signal(defaultData)
@@ -36,7 +41,7 @@ Column resizing builds on column sizing. If you only need to define starting, mi
3641

3742
### Enable Column Resizing
3843

39-
To use column resizing, add `columnResizingFeature` to your features. The `column.getCanResize()` API will return `true` by default for all columns, but you can either disable column resizing for all columns with the `enableColumnResizing` table option, or disable column resizing on a per-column basis with the `enableResizing` column option.
44+
To use column resizing, add `columnSizingFeature` and then `columnResizingFeature` to your features. The `column.getCanResize()` API will return `true` by default for all columns, but you can either disable column resizing for all columns with the `enableColumnResizing` table option, or disable column resizing on a per-column basis with the `enableResizing` column option.
4045

4146
```ts
4247
import {

docs/framework/angular/guide/column-sizing.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Want to skip to the implementation? Check out these Angular examples:
88

99
- [Column Sizing](../examples/column-sizing)
1010

11-
### Angular Setup
11+
### Column Sizing Setup
12+
13+
Here's how you set up your table to use column sizing features. Adding the column sizing feature enables the related APIs.
1214

1315
```ts
1416
import { signal } from '@angular/core'

docs/framework/angular/guide/column-visibility.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Want to skip to the implementation? Check out these Angular examples:
88

99
- [Column Visibility](../examples/column-visibility)
1010

11-
### Angular Setup
11+
### Column Visibility Setup
12+
13+
Here's how you set up your table to use column visibility features. Adding the column visibility feature enables the related APIs.
1214

1315
```ts
1416
import { signal } from '@angular/core'

docs/framework/angular/guide/composable-tables.md

Lines changed: 143 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,147 @@
11
---
2-
title: Composable Tables Guide
2+
title: Composable Tables (createTableHook) Guide
33
---
44

5-
Composable tables are app-level table factories built with `createTableHook`. Instead of repeating the same features, row models, default options, and table/cell/header components in every Angular table, you define that shared infrastructure once and consume it from each table component.
5+
`createTableHook` creates an app-specific table factory. Use it to define shared features, row models, and default table options once, then create each Angular table with the columns and data that are unique to that table.
66

7-
Use this pattern when multiple tables in an Angular app share behavior or rendering conventions. For a single isolated table, `injectTable` is usually enough.
7+
The same API can also register reusable table, cell, and header components, but component registration is optional. Start with shared options and features first; add reusable components only when your app needs standardized table UI pieces.
88

99
## Examples
1010

11-
- [Composable Tables](../examples/composable-tables) - Two tables sharing one app table setup from `src/app/table.ts`.
1211
- [Basic App Table](../examples/basic-app-table) - Minimal `createTableHook` usage without the larger component registry.
12+
- [Composable Tables](../examples/composable-tables) - Richer Users and Products tables sharing `src/app/table.ts` and reusable components.
1313

14-
## Setup
14+
## Start With Shared Features and Options
15+
16+
Create one app table hook and put the feature set, row models, and shared defaults there. This example makes sorting available to every table created by `injectAppTable`.
17+
18+
```ts
19+
import {
20+
createSortedRowModel,
21+
createTableHook,
22+
rowSortingFeature,
23+
sortFns,
24+
tableFeatures,
25+
} from '@tanstack/angular-table'
26+
27+
const features = tableFeatures({
28+
rowSortingFeature,
29+
sortedRowModel: createSortedRowModel(),
30+
sortFns,
31+
})
32+
33+
const { injectAppTable, createAppColumnHelper } = createTableHook({
34+
features,
35+
debugTable: true,
36+
enableSortingRemoval: false,
37+
})
38+
```
39+
40+
Options passed to `createTableHook` become defaults for every table created by `injectAppTable`. The `features` option is also bound to the returned column helper, so column definitions know that sorting APIs are available.
41+
42+
## Create App Columns
43+
44+
Create one column helper per row type. The helper is already bound to your app's feature set, so each table does not need to thread `typeof features` through its column definitions.
45+
46+
```ts
47+
type Person = {
48+
firstName: string
49+
lastName: string
50+
age: number
51+
visits: number
52+
}
53+
54+
const columnHelper = createAppColumnHelper<Person>()
55+
56+
const columns = columnHelper.columns([
57+
columnHelper.accessor('firstName', {
58+
cell: (info) => info.getValue(),
59+
}),
60+
columnHelper.accessor((row) => row.lastName, {
61+
id: 'lastName',
62+
header: () => 'Last Name',
63+
cell: (info) => info.getValue(),
64+
}),
65+
columnHelper.accessor('age', {
66+
header: 'Age',
67+
}),
68+
columnHelper.accessor('visits', {
69+
header: 'Visits',
70+
}),
71+
])
72+
```
73+
74+
## Create A Table
75+
76+
Create each table with `injectAppTable`. The call site provides table-specific inputs such as `columns` and `data`; shared features and defaults come from the hook.
77+
78+
```ts
79+
export class UsersTable {
80+
readonly data = signal<Array<Person>>([])
81+
82+
readonly table = injectAppTable(() => ({
83+
key: 'users-table',
84+
columns,
85+
data: this.data(),
86+
}))
87+
}
88+
```
89+
90+
## Render With The Normal Table APIs
91+
92+
You can render the table with the same table instance APIs used by a standalone `injectTable` table. This simple path does not require `appCell`, `appHeader`, `appFooter`, or registered components.
93+
94+
```html
95+
<table>
96+
<thead>
97+
@for (headerGroup of table.getHeaderGroups(); track headerGroup.id) {
98+
<tr>
99+
@for (header of headerGroup.headers; track header.id) {
100+
<th (click)="header.column.getToggleSortingHandler()?.($event)">
101+
@if (!header.isPlaceholder) {
102+
<ng-container *flexRenderHeader="header; let headerCell">
103+
{{ headerCell }}
104+
</ng-container>
105+
}
106+
</th>
107+
}
108+
</tr>
109+
}
110+
</thead>
111+
<tbody>
112+
@for (row of table.getRowModel().rows; track row.id) {
113+
<tr>
114+
@for (cell of row.getAllCells(); track cell.id) {
115+
<td>
116+
<ng-container *flexRenderCell="cell; let renderCell">
117+
{{ renderCell }}
118+
</ng-container>
119+
</td>
120+
}
121+
</tr>
122+
}
123+
</tbody>
124+
</table>
125+
```
126+
127+
## Override Shared Defaults Per Table
128+
129+
Options passed to `injectAppTable` override defaults from `createTableHook`. Use this for the few tables that need different behavior without creating a separate app hook.
130+
131+
```ts
132+
readonly table = injectAppTable(() => ({
133+
key: 'sortable-users-table',
134+
columns,
135+
data: this.data(),
136+
enableSortingRemoval: true,
137+
}))
138+
```
139+
140+
## Optional: Reusable Components
141+
142+
The richer composable-tables example also uses `createTableHook` as a component registry. Use this when several tables should share the same toolbar controls, cell renderers, header renderers, or footer renderers.
143+
144+
### Component Registry Setup
15145

16146
The composable tables example keeps the shared setup in `src/app/table.ts`. That file creates one app-specific table factory and exports the helpers used by the rest of the example.
17147

@@ -95,7 +225,7 @@ export const {
95225

96226
This file is the source of truth for the feature set, row model pipeline, row IDs, and registered components used by both tables in the example.
97227

98-
## Returned Helpers
228+
### Returned Helpers
99229

100230
| Helper | Purpose |
101231
|---|---|
@@ -105,7 +235,7 @@ This file is the source of truth for the feature set, row model pipeline, row ID
105235
| `injectTableCellContext` | Reads the current cell inside registered cell components like `TextCell`. |
106236
| `injectTableHeaderContext` | Reads the current header/footer inside registered header components like `SortIndicator`. |
107237

108-
## Columns
238+
### Component Columns
109239

110240
Use `createAppColumnHelper<TData>()` instead of the base column helper when column definitions should render registered components.
111241

@@ -132,7 +262,7 @@ readonly columns = personColumnHelper.columns([
132262

133263
The registered components are available through the enhanced `cell` and `header` objects because the column helper is bound to the `createTableHook` configuration.
134264

135-
## Table Rendering
265+
### Component Table Rendering
136266

137267
Create each table with `injectAppTable`. Per-table options provide the data and columns; shared features and row models come from `src/app/table.ts`.
138268

@@ -179,8 +309,12 @@ In templates, use the Angular rendering helpers with the app wrappers:
179309
}
180310
```
181311

182-
## Reusing The Hook
312+
### Reusing The Component Registry
183313

184314
The example has separate Users and Products table components. Both import `createAppColumnHelper` and `injectAppTable` from `src/app/table.ts`, so they share sorting, filtering, pagination, row IDs, toolbar controls, cell renderers, and header/footer renderers while keeping their own data and columns.
185315

186316
If different product areas need incompatible defaults, create another `createTableHook` setup file and export a second set of app helpers from there.
317+
318+
## When To Use This Pattern
319+
320+
Use `createTableHook` when multiple tables should share features, row models, default options, or conventions. Use the standalone `injectTable` API for a one-off table. Add the component registry only when the app wants standardized reusable table UI pieces.

docs/framework/angular/guide/expanding.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ Want to skip to the implementation? Check out these Angular examples:
88

99
- [Expanding](../examples/expanding)
1010

11-
### Angular Setup
11+
### Expanding Setup
12+
13+
Here's how you set up your table to use expanding features. Adding the expanding feature enables the related APIs. Additionally, if using client-side expanding, you also need to set up `expandedRowModel` after its associated feature because row model slots are type-checked.
1214

1315
```ts
1416
import { signal } from '@angular/core'
1517
import { injectTable, tableFeatures, rowExpandingFeature, createExpandedRowModel } from '@tanstack/angular-table'
1618

1719
const features = tableFeatures({
1820
rowExpandingFeature,
19-
expandedRowModel: createExpandedRowModel(),
21+
expandedRowModel: createExpandedRowModel(), // if using client-side expanding
2022
})
2123

2224
export class App {

0 commit comments

Comments
 (0)