addColumnFilters

addColumnFilters filters table rows by specific column values.

Options

Information:
Options passed into addColumnFilters.
const table = createTable(data, {
  colFilter: addColumnFilters({ ... }),
});
const table = createTable(data, {
  colFilter: addColumnFilters({ ... }),
});

serverSide?: boolean

If true, filtering will not change vm.current.rows. Control filtering by updating the table’s data and use plugin state to drive your fetch.

Defaults to false.

matchMode?: 'self-or-descendants' | 'self'

How rows that have sub-rows (see addSubRows) are matched.

  • 'self-or-descendants' keeps a row when it matches or when any of its descendants match, so a parent that does not match itself still appears above its matching children. This keeps the tree navigable but means a visible parent’s own cell values may fall outside the filter.
  • 'self' requires every kept row to match on its own values. A parent that does not match is removed together with its subtree.

Defaults to 'self-or-descendants'.

Column Options

Information:
Options passed into column definitions.
const columns = table.createColumns([
  table.column({
    header: 'Name',
    accessor: 'name',
    plugins: {
      colFilter: { ... },
    },
  }),
]);
const columns = table.createColumns([
  table.column({
    header: 'Name',
    accessor: 'name',
    plugins: {
      colFilter: { ... },
    },
  }),
]);

fn: ({ filterValue, value }) => boolean

Defines filter behavior for the column. Return true to keep the row.

render?: (renderProps) => RenderConfig

Renders a control on cell.current.props.[pluginName].render. renderProps extends TableState and includes:

  • id: string
  • filterValue: Box<any>: the column’s filter value; writing undefined clears it
  • values: ReadonlyBox<any[]>: the column’s values after filtering
  • preFilteredValues: ReadonlyBox<any[]>: the column’s values before filtering
  • preFilteredRows: ReadonlyBox<BodyRow[]>

render is called once per header cell. Pass the boxes to your component and read their current there, so the control stays reactive:

render: ({ filterValue, values }) => createRender(TextFilter, { filterValue, values })
render: ({ filterValue, values }) => createRender(TextFilter, { filterValue, values })
<!-- TextFilter.svelte -->
<script lang="ts">
    import type { Box, ReadonlyBox } from '@humanspeak/svelte-headless-table'

    const { filterValue, values }: {
        filterValue: Box<string | undefined>
        values: ReadonlyBox<unknown[]>
    } = $props()
</script>

<input bind:value={filterValue.current} placeholder="Search {values.current.length} rows..." />
<!-- TextFilter.svelte -->
<script lang="ts">
    import type { Box, ReadonlyBox } from '@humanspeak/svelte-headless-table'

    const { filterValue, values }: {
        filterValue: Box<string | undefined>
        values: ReadonlyBox<unknown[]>
    } = $props()
</script>

<input bind:value={filterValue.current} placeholder="Search {values.current.length} rows..." />

initialFilterValue?: any

Initial filter value, applied when the view model is created.

Warning:
Changed in v7: the initial value is applied as soon as the view model is built. 6.x applied it lazily, the first time a header cell's props were read, so an initial value on a column whose header props were never rendered had no effect. An initialFilterValue: '' on a matchFilter column now filters every row out; use undefined (or omit the option) for "no filter".

Prop Set

Information:
Extensions to the view model. Read current.props on table components. The lists below are generated from the plugin's TypeScript prop-set type, so they match the published package exactly.

HeaderCell props cell.current.props.colFilter

render: RenderConfig | undefined
The rendered filter component.

Interactions

  • Filters on hidden columns still apply. addHiddenColumns removes the cell from row.cells, not from the row’s filter data, so a column-filter value keeps narrowing the rows while the column is hidden.
  • With addExpandedRows, a sub-row is kept if it matches the filter itself or has a matching descendant (the default matchMode; use 'self' to drop non-matching parents). Register colFilter before expand so filtering happens before the tree is flattened; either order produces the same visible rows for a plain tree, but filtering first is cheaper.

Plugin State

Information:
State provided by addColumnFilters.
const vm = table.createViewModel(columns)
const { pluginStates } = vm
const { filterValues } = pluginStates.colFilter
const vm = table.createViewModel(columns)
const { pluginStates } = vm
const { filterValues } = pluginStates.colFilter

filterValues: Box<Record<string, unknown>>

Active filter values by column id. Assign a new record to change them; a column without a value (or with undefined) is not filtered.

filterValues.current = { ...filterValues.current, status: 'single' }
filterValues.current = { ...filterValues.current, status: 'single' }

preFilteredRows: ReadonlyBox<BodyRow<Item>[]>

Rows before filtering.

Examples

filterValues.current = {
  "firstName": "",
  "lastName": "",
  "age": [
    null,
    null
  ],
  "visits": 0
}
Name Info
First Name
Last Name
Age
to
Status
Visits
Profile Progress
ClaudineMoore54relationship5229
JanetGoodwin37complicated2963
DwayneConsidine25relationship9796
MaryMayert18single5264
SashaKovacek65complicated4082
AlexandreFriesen64complicated6382
TremaineBotsford35single355
GeorgianaHerman48single4958
RossHoppe42relationship9737
JaceKing56complicated257
ArchProsacco33single3693
GarnetOkuneva60single9777
OswaldoBoehm29single2236
RachaelFlatley22relationship8117
KelvinWintheiser45complicated3083
KareemFlatley19single5436
LurlineSchamberger-Kunze28single6175
GustaveHickle40relationship5426
ErnaZieme44single5564
KingMitchell32complicated247
AmieMcLaughlin55single6316
LloydNitzsche65relationship7718
OdieSchulist27relationship1541
NilsMiller64complicated3850
RansomKessler24complicated2084
LedaRatke30single055
LeopoldGreenholt38complicated5799
IsidroSanford26single1321
EugeniaSchroeder39relationship452
SamanthaCole35single9243