1

Basically, my question is that I have a dash app which follows the structure: Title, DCC Inputs, Text container, and Graph. However, I want my DCC Inputs, to update the page layout and depend upon each other. For a simplified code example, lets say I have an app layout as follows

app.layout = html.Div(children=[


    html.H1("Title", style={
        'text-align': 'center'
    }),

    dcc.Dropdown(
        id='slct_type',
        options=['type1', 'type2'],
        placeholder="Select a type",
        multi=False,
        value='',
        style={'width': '40%'}
                 ),

    html.Div(id='output_container', children=[], style={
        'textAlign': 'center'
    }),
    html.Br(),

    dcc.Graph(id='my_graph', figure={})

])

If I select type 1 in my first dcc dropdown, then I want the page to update to the following layout

app.layout = html.Div(children=[


    html.H1("Title", style={
        'text-align': 'center'
    }),

    dcc.Dropdown(
        id='slct_type',
        options=['type1', 'type2'],
        placeholder="Select a type",
        multi=False,
        value='',
        style={'width': '40%'}
                 ),

    dcc.Dropdown(
        id='slct_number',
        options=['1', '2'],
        placeholder="Select a number",
        multi=False,
        value='',
        style={'width': '40%'}
                 ),

    html.Div(id='output_container', children=[], style={
        'textAlign': 'center'
    }),
    html.Br(),

    dcc.Graph(id='my_graph', figure={})

])

Whereas is if I select type 2, I want this layout

app.layout = html.Div(children=[


    html.H1("Title", style={
        'text-align': 'center'
    }),

    dcc.Dropdown(
        id='slct_type',
        options=['type1', 'type2'],
        placeholder="Select a type",
        multi=False,
        value='',
        style={'width': '40%'}
                 ),

    dcc.Dropdown(
        id='slct_colour',
        options=['red', 'blue'],
        placeholder="Select a colour",
        multi=False,
        value='',
        style={'width': '40%'}
                 ),

    html.Div(id='output_container', children=[], style={
        'textAlign': 'center'
    }),
    html.Br(),

    dcc.Graph(id='my_graph', figure={})

])

The idea here is I always want my page format the same (title, followed by DCC input selection, followed by text output container, followed by graph) however which DCC inputs I want to put depend upon the first DCC input that the user selects. This will allow me to graph different datasets which take different parameters by first selecting the dataset type. Pls let me know if i can be more clear and thanks for any help

nasdas asdas
  • 65
  • 1
  • 7

1 Answers1

2

You can update the options and value of the second dropdown-menu using callbacks.

I give you an example: Imagine you want to select a partner for sport. There are Alice, Bob and Carol. You can play hockey, rubgy or tennis. But not every possible partner can play all these sports: Only Alice and Bob play hockey, only Bob and Carol play rugby, only Carol and Alice play tennis.

Now if you select the sport you want to only get proposed players that can actually play this sport.

You achieve this by adjusting the options of the second dropdown using callbacks. I give a working minimal example:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

possible_players = {
    'Hockey': ['Alice', 'Bob'],
    'Rugby': ['Bob', 'Carol'],
    'Tennis': ['Carol', 'Alice'],
}

app.layout = html.Div([
    'Choose the sport you want to play and with whom you want to play',
    dcc.Dropdown(
        id='sports',
        options=[
            {'label': 'Hockey', 'value': 'Hockey'},
            {'label': 'Rugby', 'value': 'Rugby'},
            {'label': 'Tennis', 'value': 'Tennis'},
        ],
        value='Hockey'
    ),
    dcc.Dropdown(
        id='players',
        options=[
            {'label': 'Alice', 'value': 'Alice'},
            {'label': 'Bob', 'value': 'Bob'},
            {'label': 'Carol', 'value': 'Carol'}
        ],
        value='Alice'
    )
])


@app.callback(
    Output('players', 'options'),
    Output('players', 'value'),
    Input('sports', 'value'),
    State('players','value'),
)
def update_players(sport,player_chosen_before_the_callback):
    player_options = possible_players[sport]
    # In case the player is still available after changing the sport, leave it as default option,
    # else just choose an arbitrary player.
    if player_chosen_before_the_callback in player_options:
        player = player_chosen_before_the_callback
    else:
        player = player_options[0]
    return [{'label': i, 'value': i} for i in player_options], player


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


Input makes triggers the callback, whereas State only lets you access the current state (of the value in our examample).

You find a tutorial for callbacks on https://dash.plotly.com/basic-callbacks

Noskario
  • 378
  • 1
  • 9
  • i do know this but i want to be able to create new dcc altogether. for example, i would sometimes want dcc dropdown and sometimes want dcc slider depending upon the input to the first dcc, so i dont think this will work for me – nasdas asdas Dec 22 '21 at 23:49
  • 2
    Sorry for that, in your example you used a dropdown for both selections, so this was not clear to me. An idea that I have is that you can simply create both elements and hide them using callbacks. See https://stackoverflow.com/questions/50213761/changing-visibility-of-a-dash-component-by-updating-other-component for more deails. – Noskario Dec 23 '21 at 08:22
  • No worries at all, thank u very much for this!!! i will look into implementing this but i THINK this will work exactly for my case- so much thanks again – nasdas asdas Dec 23 '21 at 13:38