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 ending on the chosen day;granularity(day/month/quarter/year) decides where the range starts (default: first day of the chosen date's month). Use for "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.
Give every filter a default so the first load renders with a working value. For select, the default is the id of one of the options; date filters take a token ({{today}}, {{start_of_month}}, …) or a literal ISO date.
A dashboard-level declaration looks the same, at the dashboard YAML's top level:
id: ec_business_overview
title: "What Is Happening In The Business?"
layout_mode: document
filters:
- id: global_period
type: cutoff_date
granularity: year
label: Period
default: "{{today}}"
items:
- visualization: ec_revenue_kpi
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.
Give each parameter one owner: either a dashboard-level filter or a per-viz filter, not both. When two controls bind the same parameter, one value wins on each run.
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.