Building Pages
Put everything together to create interactive dashboard pages.
Page Structure Template
Every page follows this structure:
# pages/my_page.py
# 1. IMPORTS
import dash_bootstrap_components as dbc
import ds_dash_support as ds
from dash import Input, Output, html, register_page
from data.datamanager import ddm
from ds_dash_support.themes.looker import Container, Graph
from plotly import express as px
# 2. PAGE REGISTRATION
register_page(__name__, "/my_page")
# 3. DATA CALLBACK SETUP
data_callback = ddm.data_callback(
flatten_kwargs=True,
pythonify_keys=True,
manager_filters=Input("dashboard-manager", "filters"),
applied_filters=Input("applied-filters", "data"),
)
# 4. COMPONENT DEFINITIONS
my_chart = Graph(id="my-chart")
my_tile = ds.GraphTile(
content=[my_chart],
id="my-tile",
heading="My Chart",
)
# 5. LAYOUT DEFINITION
layout = Container([
html.H1("My Page"),
dbc.Row([
dbc.Col([my_tile], lg=12),
]),
])
# 6. CALLBACKS
@data_callback(
Output("my-chart", "figure"),
)
def update_page(data):
df = data.datasets.my_dataset
fig = px.line(df, x='year', y='value')
return fig
Callbacks
Callbacks are functions that run when user input changes:
@app.callback(
Output('my-chart', 'figure'), # What to update
Input('my-filter', 'value') # What triggers it
)
def update_chart(filter_value):
data = dataset_manager.get_dataset(
'publications',
filters={'category': filter_value}
)
return px.bar(data, x='Year', y='Count')
Multiple Inputs
@app.callback(
Output('chart', 'figure'),
[Input('category-filter', 'value'),
Input('year-filter', 'value')]
)
def update_chart(category, year):
data = dataset_manager.get_dataset(
'publications',
filters={'category': category, 'year': year}
)
return px.bar(data, x='Month', y='Count')
Multiple Outputs
@app.callback(
[Output('chart', 'figure'),
Output('table', 'data'),
Output('summary', 'children')],
Input('filter', 'value')
)
def update_all(filter_value):
data = get_filtered_data(filter_value)
chart = px.bar(data, x='X', y='Y')
table_data = data.to_dict('records')
summary = f'Found {len(data)} records'
return chart, table_data, summary
Interactive Elements
Filters
from ds_dash_support import DsFilter
filter_element = DsFilter(
id='category-filter',
label='Select Category',
options=[
{'label': 'Oncology', 'value': 'oncology'},
{'label': 'Cardiology', 'value': 'cardiology'}
],
value='oncology',
searchable=True
)
Buttons
from ds_dash_support import DsButton
button = DsButton(
id='export-button',
children='Export Data',
className='btn btn-primary'
)
@app.callback(
Output('status', 'children'),
Input('export-button', 'n_clicks')
)
def on_export_click(n_clicks):
if n_clicks > 0:
export_data()
return 'Exported!'
return 'Click to export'
State Management
Store data that persists as user interacts:
from dash import dcc
# Hidden storage
app.layout = dbc.Container([
dcc.Dropdown(id='my-filter'),
html.Div(id='my-chart'),
dcc.Store(id='filtered-data-store') # Hidden storage
])
# Store filtered data
@app.callback(
Output('filtered-data-store', 'data'),
Input('my-filter', 'value')
)
def store_filtered_data(filter_value):
data = get_filtered_data(filter_value)
return data.to_dict('records')
# Use stored data
@app.callback(
Output('my-chart', 'figure'),
Input('filtered-data-store', 'data')
)
def update_chart(stored_data):
return px.bar(stored_data, x='X', y='Y')