Bojan Pavlović
Bojan Pavlović

Reputation: 113

Connecting Dropdown and RadioItems in Dash

I'm new to Dash and I'm trying to connect dcc.Dropdown and dcc.RadioItems component. For this purpose I have created this very simplyfied Dash app example in which I want to allow user to select chart (dropdown menu) based on previous input selection (RadioItems). My code works fine in terms of functionality but I'm not sure if this is the proper way to use a callback function in this case. Please find the code below:

import pandas as pd
import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.express as px
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate

data = {'date': [10, 5, 7, 11], 'column1': [15, 4, 8, 5], 'column2': [1, 2, 3, 9], 'column3': [1.5, 2.5, 3.5, 0.5]}
df = pd.DataFrame(data)
app = dash.Dash(__name__)

show_columns = ['column1', 'column2', 'column3']

app.layout = html.Div(children=[
    html.H1(children='Columns visualisation'),
    html.Div([
        html.Div(
            dcc.RadioItems(
                id='radio_items',
                options=[{'label': i, 'value': i} for i in show_columns],
                value='column1',
                labelStyle={'display': 'inline-block'}
            ),
        ),
        dcc.Dropdown(
            id='dropdown',
            options=[
                {'label': 'Line Chart', 'value': 'v1'},
                {'label': 'Bar Chart', 'value': 'v2'}
            ],
            value='v1',
         ),

        html.Div(dcc.Graph(id='graph')),
    ]),
])


@app.callback(
    Output('graph', 'figure'),
    Input('radio_items', 'value'),
    Input('dropdown', 'value')
)
def update_output(item, value):
    if item == 'column1':
        try:
            if value is None:
                raise PreventUpdate
            elif value == 'v1':
                fig = px.line(df, x=df.date, y=df.column1)
                return fig
            elif value == 'v2':
                fig1 = px.bar(df, x=df.date, y=df.column1)
                return fig1
        except ValueError:
            return None
    if item == 'column2':
        try:
            if value is None:
                raise PreventUpdate
            elif value == 'v1':
                fig = px.line(df, x=df.date, y=df.column2)
                return fig
            elif value == 'v2':
                fig1 = px.bar(df, x=df.date, y=df.column2)
                return fig1
        except ValueError:
            return None
    else:
        try:
            if value is None:
                raise PreventUpdate
            elif value == 'v1':
                fig = px.line(df, x=df.date, y=df.column3)
                return fig
            elif value == 'v2':
                fig1 = px.bar(df, x=df.date, y=df.column3)
                return fig1
        except ValueError:
            return None


if __name__ == '__main__':
    app.run_server(debug=True)

I would like to know if there is more elegant way to set up my update_output function?

Is this done this way at all?

I would appreciate any help. Thanks in advance

Upvotes: 0

Views: 1585

Answers (1)

bas
bas

Reputation: 15462

I think the checks in your example are unnecessary.

You can directly select parts of your data using the values you receive from the callback.

You could create a chart type dictionary which has "v1", "v2" as keys. The values in the dictionary could correspond to a plot function to be used for a given key:

charts = {"v1": px.line, "v2": px.bar}

Then you could change your callback to this:

@app.callback(
    Output("graph", "figure"), Input("radio_items", "value"), Input("dropdown", "value")
)
def update_output(item, chart_type):
    if chart_type is None:
        raise PreventUpdate

    return charts[chart_type](df, x=df.date, y=df[item])

You actually also don't need the if statement that checks if the chart type picked is None, because you already have set a default value in your layout so the dropdown value will never be None:

@app.callback(
    Output("graph", "figure"), Input("radio_items", "value"), Input("dropdown", "value")
)
def update_output(item, chart_type):
    return charts[chart_type](df, x=df.date, y=df[item])

Upvotes: 1

Related Questions