Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion docs/devtools.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ The devtools identify each table by the `key` table option. Registration require
const table = useTable({
key: 'users-table', // needed for devtools, omit if you don't want to use the devtools
features,
rowModels: {},
columns,
data,
})
Expand Down
75 changes: 43 additions & 32 deletions docs/framework/angular/guide/column-faceting.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@ Want to skip to the implementation? Check out these Angular examples:
import { signal } from '@angular/core'
import { injectTable, tableFeatures, columnFacetingFeature, columnFilteringFeature, createFacetedRowModel, createFacetedUniqueValues, createFacetedMinMaxValues, createFilteredRowModel, filterFns } from '@tanstack/angular-table'

const features = tableFeatures({ columnFacetingFeature, columnFilteringFeature })
const features = tableFeatures({
columnFacetingFeature,
columnFilteringFeature,
filteredRowModel: createFilteredRowModel(),
facetedRowModel: createFacetedRowModel(),
facetedUniqueValues: createFacetedUniqueValues(),
facetedMinMaxValues: createFacetedMinMaxValues(),
filterFns,
})

export class App {
readonly data = signal(defaultData)

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel(filterFns),
facetedRowModel: createFacetedRowModel(),
facetedUniqueValues: createFacetedUniqueValues(),
facetedMinMaxValues: createFacetedMinMaxValues(),
},
columns,
data: this.data(),
}))
Expand All @@ -39,7 +41,7 @@ Faceting is a feature that generates lists of values from your table's data, eit

### Column Faceting Row Models

In order to use any of the column faceting features, add the `columnFacetingFeature` to your features and the appropriate faceted row models to `rowModels`. Faceting exists to power filter UIs, so in practice you will also register the `columnFilteringFeature` and a `filteredRowModel`. Without a filtered row model, the faceted row models fall back to the pre-filtered rows and the facet values will not react to other columns' filters.
In order to use any of the column faceting features, add the `columnFacetingFeature` and the appropriate faceted row model factories to your features. Faceting exists to power filter UIs, so in practice you will also register the `columnFilteringFeature` and a `filteredRowModel`. Without a filtered row model, the faceted row models fall back to the pre-filtered rows and the facet values will not react to other columns' filters.

```ts
import {
Expand All @@ -54,16 +56,18 @@ import {
filterFns,
} from '@tanstack/angular-table'

const features = tableFeatures({ columnFacetingFeature, columnFilteringFeature })
const features = tableFeatures({
columnFacetingFeature,
columnFilteringFeature,
filteredRowModel: createFilteredRowModel(), // facet values react to other columns' filters
facetedRowModel: createFacetedRowModel(), // required for faceting (other faceted row models depend on this)
facetedMinMaxValues: createFacetedMinMaxValues(), // if you need min/max values
facetedUniqueValues: createFacetedUniqueValues(), // if you need a list of unique values
filterFns,
})

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel(filterFns), // facet values react to other columns' filters
facetedRowModel: createFacetedRowModel(), // required for faceting (other faceted row models depend on this)
facetedMinMaxValues: createFacetedMinMaxValues(), // if you need min/max values
facetedUniqueValues: createFacetedUniqueValues(), // if you need a list of unique values
},
columns,
data,
}))
Expand Down Expand Up @@ -113,39 +117,46 @@ const [min, max] = table.getGlobalFacetedMinMaxValues() ?? [0, 1];

### Custom (Server-Side) Faceting

Instead of using the built-in client-side faceting features, you can implement your own faceting logic on the server-side and pass the faceted values to the client-side. Supply custom `rowModels.facetedUniqueValues` and `rowModels.facetedMinMaxValues` factories. Each factory receives the table and a column ID and returns a thunk that resolves the faceted values. The column instance APIs (`column.getFacetedUniqueValues()` and `column.getFacetedMinMaxValues()`) will then return your server-provided values.
Instead of using the built-in client-side faceting features, you can implement your own faceting logic on the server-side and pass the faceted values to the client-side. Supply custom `facetedUniqueValues` and `facetedMinMaxValues` factories in the `features` object. Each factory receives the table and a column ID and returns a thunk that resolves the faceted values. The column instance APIs (`column.getFacetedUniqueValues()` and `column.getFacetedMinMaxValues()`) will then return your server-provided values.

```ts
readonly facetingQuery = injectQuery(() => ({
//...
}))

const features = tableFeatures({
columnFacetingFeature,
columnFilteringFeature,
facetedUniqueValues: (_table, columnId) => () => {
const uniqueValueMap = new Map<string, number>()
//... populate from facetingQuery data for this columnId
return uniqueValueMap
},
facetedMinMaxValues: (_table, columnId) => () => {
//... read from facetingQuery data for this columnId
return [min, max]
},
})

readonly table = injectTable(() => ({
features,
rowModels: {
facetedUniqueValues: (_table, columnId) => () => {
const uniqueValueMap = new Map<string, number>()
//... populate from facetingQuery data for this columnId
return uniqueValueMap
},
facetedMinMaxValues: (_table, columnId) => () => {
//... read from facetingQuery data for this columnId
return [min, max]
},
},
columns,
data,
//...
}))
```

The same factories also serve global faceting. Global faceting requests values with the internal `__global__` column ID, so you can branch on it inside the same `facetedUniqueValues` and `facetedMinMaxValues` factories to return table-wide facet values:
The same factories also serve global faceting. Global faceting requests values with the internal `__global__` column ID, so you can branch on it inside the same `facetedUniqueValues` and `facetedMinMaxValues` factory functions to return table-wide facet values:

```ts
facetedUniqueValues: (_table, columnId) => () => {
if (columnId !== '__global__') return new Map() // per-column facets
return new Map(globalFacets.uniqueValues) // global facets
},
const features = tableFeatures({
columnFacetingFeature,
columnFilteringFeature,
facetedUniqueValues: (_table, columnId) => () => {
if (columnId !== '__global__') return new Map() // per-column facets
return new Map(globalFacets.uniqueValues) // global facets
},
})
```

Alternatively, you don't have to put any of your faceting logic through the TanStack Table APIs at all. Just fetch your lists and pass them to your filter components directly.
85 changes: 39 additions & 46 deletions docs/framework/angular/guide/column-filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@ Want to skip to the implementation? Check out these Angular examples:
import { signal } from '@angular/core'
import { injectTable, tableFeatures, columnFilteringFeature, createFilteredRowModel, filterFns } from '@tanstack/angular-table'

const features = tableFeatures({ columnFilteringFeature })
const features = tableFeatures({
columnFilteringFeature,
filteredRowModel: createFilteredRowModel(),
filterFns,
})

export class App {
readonly data = signal(defaultData)

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel(filterFns),
},
columns,
data: this.data(),
}))
Expand Down Expand Up @@ -60,14 +61,13 @@ If you're not sure, you can always start with client-side filtering and paginati

If you have decided that you need to implement server-side filtering instead of using the built-in client-side filtering, here's how you do that.

No `filteredRowModel` is needed for manual server-side filtering. Instead, the `data` that you pass to the table should already be filtered. However, if you have added a `filteredRowModel` to `rowModels`, you can tell the table to skip it by setting the `manualFiltering` option to `true`.
No `filteredRowModel` is needed for manual server-side filtering. Instead, the `data` that you pass to the table should already be filtered. However, if you have added a `filteredRowModel` to features, you can tell the table to skip it by setting the `manualFiltering` option to `true`.

```ts
const features = tableFeatures({ columnFilteringFeature })

readonly table = injectTable(() => ({
features,
rowModels: {}, // no filteredRowModel needed for manual server-side filtering
data,
columns,
manualFiltering: true,
Expand All @@ -78,7 +78,7 @@ readonly table = injectTable(() => ({

### Client-Side Filtering

If you are using the built-in client-side filtering features, add the `columnFilteringFeature` to your features and the `filteredRowModel` to your row models. Import `createFilteredRowModel` and `filterFns` from TanStack Table:
If you are using the built-in client-side filtering features, add the `columnFilteringFeature` and the `filteredRowModel` factory to your features. Import `createFilteredRowModel` and `filterFns` from TanStack Table:

```ts
import {
Expand All @@ -89,13 +89,14 @@ import {
filterFns,
} from '@tanstack/angular-table'

const features = tableFeatures({ columnFilteringFeature })
const features = tableFeatures({
columnFilteringFeature,
filteredRowModel: createFilteredRowModel(),
filterFns,
})

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel(filterFns),
},
data,
columns,
}))
Expand Down Expand Up @@ -124,7 +125,6 @@ You can access the column filter state from the table instance with `table.atoms
```ts
readonly table = injectTable(() => ({
features,
rowModels: { filteredRowModel: createFilteredRowModel(filterFns) },
columns,
data,
//...
Expand All @@ -148,7 +148,6 @@ export class App {

readonly table = injectTable(() => ({
features,
rowModels: { filteredRowModel: createFilteredRowModel(filterFns) },
columns,
data: this.data(),
//...
Expand All @@ -169,7 +168,6 @@ readonly columnFilters = signal<ColumnFiltersState>([])
//...
readonly table = injectTable(() => ({
features,
rowModels: { filteredRowModel: createFilteredRowModel(filterFns) },
columns,
data: this.data(),
//...
Expand All @@ -190,7 +188,6 @@ If you do not need to control the column filter state in your own state manageme
```ts
readonly table = injectTable(() => ({
features,
rowModels: { filteredRowModel: createFilteredRowModel(filterFns) },
columns,
data,
//...
Expand Down Expand Up @@ -278,33 +275,26 @@ const columns = [
}
]
//...
const features = tableFeatures({
columnFilteringFeature,
filteredRowModel: createFilteredRowModel(),
filterFns: {
...filterFns,
myCustomFilterFn: (row, columnId, filterValue) => {
return // true or false based on your custom logic
},
startsWith: startsWithFilterFn, // defined elsewhere
},
})

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel({
...filterFns,
myCustomFilterFn: (row, columnId, filterValue) => {
return // true or false based on your custom logic
},
startsWith: startsWithFilterFn, // defined elsewhere
}),
},
columns,
data,
}))
```

> **TypeScript Note:** For `filterFn: 'myCustomFilterFn'` string references to typecheck, augment the `FilterFns` interface with a `declare module` block:
>
> ```ts
> declare module '@tanstack/angular-table' {
> interface FilterFns {
> myCustomFilterFn: FilterFn<typeof features, MyData>
> }
> }
> ```
>
> Alternatively, skip the registry and the augmentation entirely by passing the function directly to the `filterFn` column option. See the [Fuzzy Search example](../examples/filters-fuzzy) for a complete registration with module augmentation.
> **TypeScript Note:** For `filterFn: 'myCustomFilterFn'` string references to typecheck, register the function in the `filterFns` slot on `tableFeatures` (as shown above). Alternatively, skip the registry entirely by passing the function directly to the `filterFn` column option. See the [Fuzzy Search example](../examples/filters-fuzzy) for a complete registration example.

##### Customize Filter Function Behavior

Expand Down Expand Up @@ -356,7 +346,6 @@ const columns = [
//...
readonly table = injectTable(() => ({
features,
rowModels: { filteredRowModel: createFilteredRowModel(filterFns) },
columns,
data,
enableColumnFilters: false, // disable column filtering for all columns
Expand All @@ -374,14 +363,16 @@ By default, filtering is done from parent rows down, so if a parent row is filte
However, if you want to allow sub-rows to be filtered and searched through, regardless of whether the parent row is filtered out, you can set the `filterFromLeafRows` table option to `true`. Setting this option to `true` will cause filtering to be done from leaf rows up, which means parent rows will be included so long as one of their child or grand-child rows is also included.

```ts
const features = tableFeatures({ columnFilteringFeature, rowExpandingFeature })
const features = tableFeatures({
columnFilteringFeature,
rowExpandingFeature,
filteredRowModel: createFilteredRowModel(),
expandedRowModel: createExpandedRowModel(),
filterFns,
})

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel(filterFns),
expandedRowModel: createExpandedRowModel(),
},
columns,
data,
filterFromLeafRows: true, // filter and search through sub-rows
Expand All @@ -395,14 +386,16 @@ By default, filtering is done for all rows in a tree, no matter if they are root
Use `maxLeafRowFilterDepth: 0` if you want to preserve a parent row's sub-rows from being filtered out while the parent row is passing the filter.

```ts
const features = tableFeatures({ columnFilteringFeature, rowExpandingFeature })
const features = tableFeatures({
columnFilteringFeature,
rowExpandingFeature,
filteredRowModel: createFilteredRowModel(),
expandedRowModel: createExpandedRowModel(),
filterFns,
})

readonly table = injectTable(() => ({
features,
rowModels: {
filteredRowModel: createFilteredRowModel(filterFns),
expandedRowModel: createExpandedRowModel(),
},
columns,
data,
maxLeafRowFilterDepth: 0, // only filter root level parent rows out
Expand Down
5 changes: 0 additions & 5 deletions docs/framework/angular/guide/column-ordering.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export class App {

readonly table = injectTable(() => ({
features,
rowModels: {},
columns,
data: this.data(),
}))
Expand Down Expand Up @@ -55,7 +54,6 @@ const features = tableFeatures({ columnOrderingFeature })

readonly table = injectTable(() => ({
features,
rowModels: {},
//...
initialState: {
columnOrder: ['columnId1', 'columnId2', 'columnId3'],
Expand Down Expand Up @@ -88,7 +86,6 @@ export class App {

readonly table = injectTable(() => ({
features,
rowModels: {},
//...
atoms: {
columnOrder: this.columnOrderAtom,
Expand All @@ -109,7 +106,6 @@ readonly columnOrder = signal<ColumnOrderState>(['columnId1', 'columnId2', 'colu
//...
readonly table = injectTable(() => ({
features,
rowModels: {},
//...
state: {
columnOrder: this.columnOrder(),
Expand Down Expand Up @@ -138,7 +134,6 @@ const features = tableFeatures({ columnOrderingFeature })
export class App {
readonly table = injectTable(() => ({
features,
rowModels: {},
columns,
data: this.data(),
initialState: {
Expand Down
Loading
Loading