# Faceting (Vue) Guide

## Examples

Want to skip to the implementation? Check out these Vue examples:

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

Vue refs can be passed directly where the adapter expects reactive table options.

### Vue Setup

```ts
import { useTable, tableFeatures, columnFacetingFeature, columnFilteringFeature, createFacetedRowModel, createFacetedUniqueValues, createFacetedMinMaxValues, createFilteredRowModel, filterFns } from '@tanstack/vue-table'

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

const table = useTable({
  features,
  columns,
  data,
})
```

## Faceting (Vue) Guide

Faceting is a feature that generates lists of values from your table's data, either for a single column (column faceting) or across the entire table (global faceting). For example, a list of unique values can be used as search suggestions in an autocomplete filter component, or a tuple of minimum and maximum values from a column of numbers can drive a range slider filter component. The same row models power both the per-column and table-wide APIs.

### 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 model factories to `tableFeatures`. 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 {
  useTable,
  tableFeatures,
  columnFacetingFeature,
  columnFilteringFeature,
  createFacetedRowModel,
  createFacetedMinMaxValues,
  createFacetedUniqueValues,
  createFilteredRowModel,
  filterFns,
} from '@tanstack/vue-table'

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,
})

const table = useTable({
  features,
  columns,
  data,
})
```

First, you must include the `facetedRowModel`. This row model will generate a list of values for a given column. If you need a list of unique values, include the `facetedUniqueValues` row model. If you need a tuple of minimum and maximum values, include the `facetedMinMaxValues` row model.

### Use Faceted Row Models

Once you have registered the appropriate row model factories in `tableFeatures`, you will be able to use the faceting column instance APIs to access the lists of values generated by the faceted row models.

```ts
// list of unique values for autocomplete filter
const autoCompleteSuggestions = 
 Array.from(column.getFacetedUniqueValues().keys())
  .sort()
  .slice(0, 5000);
```

```ts
// tuple of min and max values for range filter
const [min, max] = column.getFacetedMinMaxValues() ?? [0, 1];
```

### Global Faceting

The same `columnFacetingFeature` and faceted row models also power table-wide (global) faceting. Where column faceting derives values from a single column, global faceting derives values across all columns, which is useful for populating a global filter's autocomplete suggestions or a global range slider. If your table also uses global filtering, register the `globalFilteringFeature` so global facet values react to the active global filter.

Use the global faceting table instance APIs to read the values:

```ts
const globalFacetedRows = table.getGlobalFacetedRowModel().flatRows
```

```ts
// list of unique values for autocomplete filter
const autoCompleteSuggestions =
 Array.from(table.getGlobalFacetedUniqueValues().keys())
  .sort()
  .slice(0, 5000);
```

```ts
// tuple of min and max values for range filter
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 `facetedUniqueValues` and `facetedMinMaxValues` factories in `tableFeatures`. 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
const facetingQuery = useQuery(
  //...
)

const features = tableFeatures({
  columnFacetingFeature,
  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]
  },
})

const table = useTable({
  features,
  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 (registered on `tableFeatures`) 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
},
```

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.
