Global Filtering
A global filter is a single value, usually a search box, tested against every searchable column at once. A row survives when at least one of those columns matches. This page is the port of TanStack Table's Global Filtering guide; per-column filters are on Column Filtering.
The global filter and the column filters are applied by the same
filteredRowModel stage of the pipeline, and a row has to
pass both.
filteredRows : Table.State -> Table.RowModel Person
filteredRows state =
Table.filteredRowModel config state (unfilteredRows state)
Global filter state
State.globalFilter is one Value, not a list, because there
is only ever one global filter. Value.Null means "no global filter".
-- State.globalFilter : Value
-- Table.initialState.globalFilter == Value.Null
A search box writes Value.String. The slice is a Value rather than a
String so a custom global filter function can take a range, a set of choices,
or anything else Value can hold, which is what TanStack's any typing of
this slice is for.
Config options
| Option | Type | Default | Description |
|---|---|---|---|
enableGlobalFilter |
Bool |
True |
Global filtering for every column. |
enableFilters |
Bool |
True |
Both column and global filtering. False switches off both. |
globalFilterFn |
Maybe FilterFn |
Nothing |
The comparison the global filter uses. Nothing means the automatic choice. Set it with Table.withGlobalFilterFn. |
getColumnCanGlobalFilter |
Maybe (Column row -> Bool) |
Nothing |
Decide per column whether the global filter searches it. Nothing uses the default rule below. |
manualFiltering |
Bool |
False |
True makes Table.filteredRowModel return its input untouched. |
Table.withGlobalFilterFn is the one builder here; the other fields are set
with a record update on Table.config.
config : Table.Config Person
config =
Table.config columns
|> Table.withGetRowId (\person _ _ -> person.id)
|> Table.withGlobalFilterFn FilterFn.includesString
A column is searched by the global filter when all of these hold: it has an
accessor, Config.enableFilters and Config.enableGlobalFilter are on, the
column has not opted out with withEnableGlobalFilter False, and
Config.getColumnCanGlobalFilter agrees. The default rule, when that field is
Nothing, keeps a column only if its first non-null value is a string or a
number, which is TanStack's default.
namesOnlyConfig : Table.Config Person
namesOnlyConfig =
let
base : Table.Config Person
base =
Table.config columns
in
{ base
| getColumnCanGlobalFilter =
Just
(\column ->
List.member (Table.columnId column) [ "firstName", "lastName" ]
)
}
Global filter function
Config.globalFilterFn takes the same Table.FilterFn.FilterFn a column takes.
The full list of built-ins, the four parts of a FilterFn, and how to write
your own are on Column Filtering.
TanStack's guide lists the subset of its filter functions that make sense
against a mixed set of columns, leaving out the ones that only suit a single
typed column. The same subset applies here: includesString,
includesStringSensitive,
equalsString, equals, weakEquals, arrHas, arrIncludes,
arrIncludesAll, arrIncludesSome, inNumberRange, between, and
betweenInclusive all work against a mixed set of columns.
With no globalFilterFn set, the global filter uses
globalAutoFilterFn, which is
Table.FilterFn.includesString.
Column options
| Builder | Type | Default | Description |
|---|---|---|---|
withEnableGlobalFilter |
Bool -> Column row -> Column row |
Nothing |
Whether the global filter searches this column. Nothing falls back to Config.enableGlobalFilter and Config.getColumnCanGlobalFilter. |
There is no per-column global filter function: the global filter uses one comparison for every column it searches.
columns : List (Table.Column Person)
columns =
[ Table.column "firstName" (.firstName >> Value.String)
|> Table.withHeader "First name"
, Table.column "lastName" (.lastName >> Value.String)
|> Table.withHeader "Last name"
, Table.column "department" (.department >> Value.String)
|> Table.withHeader "Department"
, Table.column "id" (.id >> Value.String)
|> Table.withHeader "ID"
|> Table.withEnableGlobalFilter False
]
Transitions
| Function | What it does |
|---|---|
setGlobalFilter |
Set the global filter value. |
resetGlobalFilter |
Clear it, back to Value.Null. |
update : Msg -> Table.State -> Table.State
update msg state =
case msg of
SearchTyped typed ->
Table.setGlobalFilter (Value.String typed) state
SearchCleared ->
Table.resetGlobalFilter state
Neither takes a RowModel. Unlike
setColumnFilter, the global filter
value is stored as written: there is no autoRemove step, so an empty search
string is kept in state and simply matches everything.
Queries
| Function | Use it for |
|---|---|
getCanGlobalFilter |
Listing or debugging which columns the search box actually searches. |
getGlobalFilterFn |
Showing which comparison the search uses. Always returns a FilterFn. |
globalAutoFilterFn |
The default, Table.FilterFn.includesString. It is a value, not a function. |
globalFacetKey |
The column id "__global__", which the faceting functions take to mean "across every globally filterable column". See Faceting. |
Read the current value straight off the state; there is no getter for it.
viewSearchInput : Table.State -> Html Msg
viewSearchInput state =
input
[ value (Value.toString state.globalFilter)
, placeholder "Search"
, onInput SearchTyped
]
[]
getCanGlobalFilter takes a RowModel because the default column rule samples
the data for the column's value type. Pass the row model you handed to
Table.filteredRowModel.
searchedColumnIds : Table.State -> List String
searchedColumnIds state =
Table.leafColumns config
|> List.map Table.columnId
|> List.filter (Table.getCanGlobalFilter config (unfilteredRows state))
What this page does not cover
- Controlled state,
onGlobalFilterChange, and atoms. TheStateis always yours. See Table State. initialState.globalFilter. CallsetGlobalFilteronTable.initialState.resetGlobalFilter(true).resetGlobalFilteralways clears the value; there is no "back to the initial state" variant, because the package does not keep a copy of your starting state.- The
filterFnsregistry.Config.globalFilterFnholds the function itself, not a registered name. - A global filter UI. As in TanStack, no input is rendered for you. Wire one up as shown above.
Example
Column Filters, ported from TanStack's Filters example, which includes a global search box.