Skip to content

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')