What a filter is in Looky
A filter is a user-facing control on a visualization or a dashboard. The user picks a value; Looky sends it to the underlying Malloy query as a named parameter. Filters live in the visualization (or dashboard) YAML under filters: [], one entry per control.
Filters and cross-filtering are different mechanisms. Filters are declarative controls the user explicitly interacts with. Cross-filtering is automatic — clicking on a chart inside a dashboard adds a "pill" that becomes a parameter without any YAML.
Choosing a filter type
Five filter types are supported. Pick the one whose UI matches the input the user is choosing.
select— dropdown picker. The option list is either declared in YAML or resolved dynamically by running a Malloy query at page load.cutoff_date— single date that automatically expands to adate_from/date_torange running from the first day of that month to the chosen day. Use for "month-to-date as of" reports.date_range— open from / to date picker. Use when the user needs to pick both endpoints freely.date_range_preset— date range chosen from named presets (last_30_days, this_month, last_month, this_year, etc.). The default for most operational dashboards.month— year + month picker with configurable bounds. Use when the analysis is keyed on a single month (monthly close, monthly billing).
Other filter types are not supported.
Anatomy of a filter declaration
Every filter entry is an object with at least a type. The other keys depend on the type — see each type's reference page for the full list.
id: orders_grid
type: grid
query: "models/ec_fulfillment.malloy::detail"
filters:
- type: select
id: status
label: Status
param: status
options_query: "models/ec_fulfillment.malloy::status_options"
default: all
- type: date_range_preset
id: period
label: Period
default:
preset: last_30_days
The order in the array is the order the controls render in the UI.
How a filter value reaches the Malloy query
The value picked in the filter control is sent to the query as a named parameter. The model declares the parameter and uses it inside the query.
- For select, cutoff_date, and month, the parameter name is whatever you put in the filter's
paramfield (or, when omitted, the filter'sid). - For date_range and date_range_preset, the parameters are
date_fromanddate_toby default. Override the names through the filter'sbindings: { date_from, date_to }block when the model expects different parameter names.
Naming convention: parameters whose Malloy name starts with p_ have the prefix stripped for the external name. A model parameter declared as p_start_date is set by sending start_date. See Malloy support.
Where filters live
- On a single visualization. Use the visualization's
filters: []when the control is local to that chart — for example, a per-grid status filter. - On a dashboard. Use the dashboard's
filters: []when the control should narrow every viz on the page — for example, a global "Period" filter at the top of an executive dashboard.
A dashboard-level filter applies to every viz the dashboard contains, but only if each viz's underlying model declares the matching parameter.
Filters vs cross-filtering
Filters are declarative — you decide in YAML which controls the user sees. Cross-filtering is interactive — the user clicks a chart and the dashboard adds the implied filter as a pill. Both end up in the same place: a Malloy parameter on the next run. The only difference is who initiates the filter.
For most dashboards, mix the two: a small set of declared filters at the top (period, region, channel) plus the implicit cross-filter that responds to clicks. See Cross-filtering.
Adapter differences
Filter UI behaves the same on any source. Differences appear when the filter value is bound to the underlying parameter — most importantly for date / timestamp filters against Postgres- or MySQL-backed models, which use the raw-SQL @param placeholder pattern (each @param declared on the source signature, value substituted into the SQL string at run time). See Source adapter differences and Models.
Common pitfalls
- The filter shows up but does not narrow the data. The model must declare a parameter with the matching name (after the
p_prefix is stripped) inside the source's parentheses. Check the source signature in the.malloyfile. - Two filters bind to the same parameter. Only one wins. Pick a single source of truth per parameter — either a dashboard-level filter or a per-viz filter, not both.
- Validate fails with
unbound_param. The model uses a raw-SQL@paramplaceholder that is not declared on the source signature. The error names the missing parameter — add it to the source's parentheses. - Date filter on a Postgres or MySQL model fails. Use the raw-SQL
@paramplaceholder pattern in the model's SQL with a matching declaration on the source signature — see Source adapter differences. - The default value does not load. For
select, the default must match theidof one of the options. For date filters, use the supported tokens (,, etc.) or a literal ISO string. - The filter expects a value the user does not provide. Either set a sensible default in the filter, or declare a default on the source signature so the query still runs when the parameter is missing.