Filters
Let readers narrow queries with field-backed or manual filters
A filter is a control that holds a condition on a field. Create it, map it to the queries it should affect, then set its condition when the reader changes an input.
Creating a filter
A field-backed filter takes its options from the field, limited by the reader's permissions. field follows the field reference rules and is checked immediately:
const region = app.createFilter('region', {
dataset: 'sales',
field: 'users.region',
label: 'Region',
})
await region.loadOptions() // or loadOptions('ap') to search
region.options // the loaded valuesA manual filter has no field. You supply the type, plus a fixed list of options or nothing for free input:
const tier = app.createFilter('tier', { type: 'string', options: ['Gold', 'Silver'] })Always pass dataset alongside field. It is only optional when the reader can see exactly one dataset, which is rare. An unknown field throws a ValidationError with a "did you mean" suggestion.
Setting a condition
Set the value with a condition, then call app.execute():
region.setCondition({ operator: 'is', values: ['APAC', 'EMEA'] }) // IN list
region.setCondition({ operator: 'is', values: [] }) // no filter
region.reset() // back to the declared defaultA condition with no values, or with operator: 'none', sends nothing, so the query runs unfiltered. Give a filter a starting value with default:
app.createFilter('region', {
dataset: 'sales',
field: 'users.region',
default: { operator: 'is', values: ['APAC'] },
})Operators
| Type | Operators |
|---|---|
| Any | is, is_not, is_null, not_null |
| String | contains, does_not_contain, starts_with, ends_with (all case-insensitive) |
| Number | greater_than, less_than, between (values: [lo, hi]) |
| Date | between (['2026-01-01', '2026-03-31']), before, after, last and next (values: [7], modifier: 'day'), matches (['last 3 months'], an AQL date phrase) |
| Boolean | is_true, is_false |
The full list is in the SDK's Operator type.
matches_user_attribute and the transform_pop_* operators are not supported on anfra. A query they reach fails with a QueryError.
Mapping to queries
A filter affects no query until you map it with app.mapControl(). See Controls for mappings, including conditions on aggregates.
Related
- Controls: how a filter reaches a query.
- Date drill: the other kind of control.
- Example app: a region filter driving two charts.