| name | wiring-vizro-actions |
| description | Use this skill when adding cross-filter, cross-highlight, drill-through, or data export interactions to a Vizro dashboard — both for choosing the right interaction pattern during design and for implementing actions in code. Activate when the user wants clicks on a chart or table to filter or highlight other charts, tables, or figures, needs cross-page navigation with pre-set filters, or wants users to download data. |
Wiring Vizro Actions
Core concept: Source → Control → Target
All advanced interactions follow the same shape:
- A source component triggers
va.set_control when the user clicks it. Practical sources are vm.Graph and vm.AgGrid — they carry click-data (column values from the clicked point/cell) that can drive a dynamic filter. (vm.Figure/vm.Button/vm.Card technically support set_control too, but only with a hardcoded literal value, so they are not useful for cross-filtering.)
set_control writes a value into an intermediate control (vm.Filter or vm.Parameter) with an explicit id.
- The control updates target components. Filter/Parameter targets are data-bearing components:
vm.Graph, vm.AgGrid, vm.Figure, vm.Table.
The control is always explicit — you do not connect components directly. This makes interactions composable (you can wire multiple sources to the same control, or one source to multiple controls).
Built-in actions
| Action | Purpose | Trigger |
|---|
va.export_data() | Download all on-page data as CSV (respects filters) | vm.Button |
va.set_control(control=..., value=...) | Set the value of a Filter or Parameter | vm.Graph or vm.AgGrid |
import vizro.actions as va. Built-in actions are passed directly into actions= — wrapping them in vm.Action raises an error (deliberate: built-ins have their own predefined inputs/outputs and would conflict with vm.Action's).
vm.Button(text="Export data", actions=va.export_data())
vm.Graph(actions=va.set_control(control="region_filter", value="y"))
vm.Graph(actions=[vm.Action(function=va.set_control(...))])
Named interaction patterns
Match data shape + user need to a pattern. Full details (when-to-use, wireframes, spec entries, code) in actions-reference.md.
| # | Pattern | When to use | Key mechanic |
|---|
| 1 | Hierarchical Drill-Down (cross-page) | 2–3 level hierarchy where detail needs a dedicated page | cross-filter + show_in_url=True + back button + export |
| 2 | Single-Page Drill-Down (container) | 2-level hierarchy where detail fits in a container | cross-filter into a container |
| 3 | Comparison Spotlight (cross-highlight) | Compare one entity against many without removing context | custom chart with highlight_X + hidden Parameter |
| 4 | Multi-Dimensional Slice | 2+ categorical dimensions (e.g. day × time heatmap) | actions chain → multiple Filters |
| 5 | Data Export | Analyst persona needs the filtered data downloaded | vm.Button + va.export_data() |
Decision flow (pick at most one of Patterns 1–4 as the primary interaction, then independently add Pattern 5 if export is needed):
Does the data have a natural hierarchy (group → individual → detail)?
├─ YES, detail needs its own page → Pattern 1
├─ YES, detail fits in a container → Pattern 2
└─ NO → continue
Compare one entity against many without removing context?
├─ YES → Pattern 3
└─ NO → continue
2+ categorical dimensions, click to drill into one cell?
├─ YES → Pattern 4
└─ NO → A standard sidebar vm.Filter is sufficient — no advanced pattern needed.
Then independently: does the user need to download data?
├─ YES → add Pattern 5 (Data Export button) on top of whichever pattern you chose above (or on its own)
└─ NO → done
When NOT to use advanced interactions
Use a chart or table as a Filter/Parameter source only when the user explicitly asks for it, or when a pattern's "When to use" clause clearly matches. The bullets below are common cases where the sidebar wins.
- View-only dashboards (executive summary — users glance, not explore)
- Simple filtering needs (a sidebar dropdown covers it)
- Small datasets (< ~5 groups — a filter is simpler and clearer)
- More than 2 interaction patterns per page (becomes confusing)
Key gotchas
custom_data for non-positional values: When cross-filtering from a graph using a column that is not on a positional axis (x/y/z/lat/lon), add custom_data="column" to the figure and use value="column" in set_control. Otherwise the click does nothing.
visible=False for cross-highlight: When a Parameter is the highlight control, hide its selector — the highlight effect itself is the feedback. Also set visible=False on a cross-filter when the user explicitly requests it.
"NONE" in highlight Parameter selector options: Include "NONE" as the first option so the chart starts unhighlighted.
show_in_url=True for cross-page: Required on the target Filter. Without it, Vizro raises ValueError at build time and the app won't start.
- Back button + Flex layout for drill-through targets: Pages that receive a drill-through must use
layout=vm.Flex(direction="column") so the back button takes natural height (Grid would waste a full 140px+ row). Put remaining content in a vm.Container with its own vm.Grid.
- Header hint on interactive source: Always add a short, action-oriented
header (e.g. header="Click a bar to filter by region") so users know the component is clickable.
- Don't use
filter_interaction: It is deprecated. Use va.set_control instead.
Quick code recipes
Export data (Pattern 5)
vm.Button(text="Export data", actions=va.export_data())
Cross-filter from chart (Pattern 1 or 2)
vm.Graph(
header="Click a bar to filter by region",
figure=px.bar("data", x="value", y="region", orientation="h"),
actions=va.set_control(control="region_filter", value="y"),
)
vm.Filter(id="region_filter", column="region")
Actions chain — one click sets multiple controls (Pattern 4)
vm.Graph(
header="Click a cell to filter the table below",
figure=px.density_heatmap("appointments", x="day", y="time_slot"),
actions=[
va.set_control(control="day_filter", value="x"),
va.set_control(control="time_filter", value="y"),
],
)
vm.Filter(id="day_filter", column="day", targets=["appointments_table"])
vm.Filter(id="time_filter", column="time_slot", targets=["appointments_table"])
Cross-page drill-through (Pattern 1)
vm.AgGrid(
header="Click a row to view details",
figure=dash_ag_grid("reps"),
actions=va.set_control(control="rep_filter", value="rep_name"),
)
vm.Page(
title="Rep Detail",
layout=vm.Flex(direction="column"),
components=[
vm.Button(text="← Back", href="/", variant="outlined"),
vm.Container(layout=vm.Grid(...), components=[...]),
],
controls=[vm.Filter(id="rep_filter", column="rep_name", show_in_url=True)],
)
Deep dive
Load actions-reference.md when you need:
| Need | Search for |
|---|
| Full pattern template (when/why/code/wireframe/spec) | ## Pattern N |
| Highlight-aware custom chart wiring (chart shape + Parameter wiring) | ## Pattern 3 |
| Multi-dimensional / actions chain | ## Pattern 4 |
Drill-through layout constraint (Flex/Grid/back button, href slug format) | ## Pattern 1 |
Positional vs custom_data and the @capture("graph") signature gotcha | ## Common Implementation Mistakes |
| Full common-mistakes table | ## Common Implementation Mistakes |
Key imports
import vizro.actions as va
import vizro.models as vm
import vizro.plotly.express as px
from vizro.tables import dash_ag_grid
from vizro.models.types import capture