Interactive Board Example¶
A board with variables and filters that update charts dynamically, built on the Dundersign demo dataset — paste it into the playground and it renders as-is.
Complete Board¶
title: "Document Activity with Filters"
source: db
variables:
status:
input: select
options:
static: ["sent", "completed"]
# No default: starts on All statuses
date_range:
input: daterange
# No default: starts on the full history
min_pages:
input: slider
min: 1
max: 20
step: 1
default: 1
queries:
filtered_documents:
sql: |
SELECT
status,
COUNT(*) AS documents,
ROUND(AVG(page_count), 1) AS avg_pages,
ROUND(AVG(days_to_complete), 1) AS avg_days_to_complete
FROM dundersign.documents
WHERE {{ filter('status', status) }}
AND {{ filter_date_range('created_at', date_range) }}
AND {{ filter('page_count', min_pages, '>=') }}
GROUP BY status
ORDER BY documents DESC
monthly:
sql: |
SELECT month, revenue, active_users
FROM dundersign_serving.monthly_metrics
WHERE {{ filter_date_range('month', date_range) }}
AND month > (SELECT MIN(month) FROM dundersign_serving.monthly_metrics)
AND month < (SELECT MAX(month) FROM dundersign_serving.monthly_metrics)
ORDER BY month
rows:
- title: "Filtered Document View"
grid:
columns: 24
items:
- item: documents_chart
width: 12
- item: revenue_chart
width: 12
- item: documents_table
width: 24
charts:
documents_chart:
title: "Documents by Status"
query: queries.filtered_documents
type: bar
x: status
y: documents
revenue_chart:
title: "Revenue by Month"
query: queries.monthly
type: line
x: month
y: revenue
documents_table:
title: "Status Details"
query: queries.filtered_documents
type: table
Note how date_range is wired into both queries — one variable can drive
any number of charts.
How Variables Work¶
Variable Definition¶
Variables are defined at the board level:
variables: status: input: select options: static: ["sent", "completed"] # No default: starts on All statuses
input: The UI component (select, slider, daterange, etc.)options: Available options (static list or dynamic query)default: Initial value — omit it to start unfiltered
Wiring Variables to Queries¶
Variables are referenced in the query SQL — the filter() helper skips the
condition entirely when its variable is unset:
queries: filtered_documents: sql: | SELECT status, COUNT(*) AS documents FROM dundersign.documents WHERE {{ filter('status', status) }} AND {{ filter_date_range('created_at', date_range) }} AND {{ filter('page_count', min_pages, '>=') }} GROUP BY status
When a variable changes, the query automatically re-executes with the new values.
User Interaction Flow¶
- User selects status from dropdown →
statusvariable updates - User adjusts date range →
date_rangevariable updates - User moves slider →
min_pagesvariable updates - Query re-executes with new filter values
- Charts update automatically with new data
Key Concepts¶
Handling "All" Values¶
When a variable can be "All", filter() already does the right thing for an
unset value; for an explicit "All" option, use a Jinja conditional in the SQL:
This shows all statuses when "All" is selected, otherwise filters to the selected status.
Multiple Variable Types¶
This example shows three common variable types: - Select: Single choice dropdown - Date range: Date range picker - Slider: Numeric range input
Grid Layout with Multiple Charts¶
Using grid layout to show multiple charts:
grid: columns: 24 items: - item: documents_chart width: 12 - item: revenue_chart width: 12 - item: documents_table width: 24
Extensions¶
Add More Variables¶
Add additional filters:
variables: priority: input: multiselect options: static: ["low", "normal", "high", "urgent"] default: ["high", "urgent"]
Dynamic Options¶
Load options from a query:
variables: template: input: select options: query: queries.template_list
Related¶
- Variables Guide - Learn about variables
- Expressions Guide - Learn about variable references
- Drill-Down Example - Planned click filtering