I have a slave dropdown list in my application whose options change based on the value selected in a master dropdown. This part is working as expected. I would also like to add a button which, when the user selects it, causes a default value to be written to the dropdown from a callback (overriding any existing selected value). This works fine too. However, this value will not persist if I switch the master dropdown selection to another value and then back to the original selection. Persistence works fine as long as the slave drowpdown contains a user selected value.
I modified a sample application from the Plotly website to illustrate my issue. If you click the ‘default’ button, it will overwrite the ‘neighborhood’ dropdown with a default value. If you then change the city and come back to the previously selected city, the neighborhood drodown is blank. However, if you manually select a neighborhood, change the city and come back - the neighborhood value persists.
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
CITIES = ['Boston', 'London', 'Montreal']
NEIGHBORHOODS = {
'Boston': ['Back Bay', 'Fenway', 'Jamaica Plain'],
'London': ['Canary Wharf', 'Hackney', 'Kensington'],
'Montreal': ['Le Plateau', 'Mile End', 'Rosemont']
}
DEFAULT_NEIGHBORHOODS = {
'Boston': 'Back Bay',
'London': 'Kensington',
'Montreal': 'Le Plateau'
}
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
'Choose a city:',
dcc.Dropdown(
id='persisted-city',
value='Montreal',
options=[{'label': v, 'value': v} for v in CITIES],
persistence=True
),
html.Br(),
'correlated persistence - choose a neighborhood:',
html.Div([
dcc.Dropdown(id='neighborhood'),
], id='neighborhood-container'),
html.Br(),
dbc.Button('default', id='default_neighborhood'),
html.Div(id='persisted-choices')
])
@app.callback(
Output('neighborhood-container', 'children'),
[Input('persisted-city', 'value'),
Input('default_neighborhood', 'n_clicks')]
)
def set_neighborhood(city, default_button_clicks):
neighborhoods = NEIGHBORHOODS[city]
ctx = dash.callback_context
triggered_input = ctx.triggered[0]['prop_id'].split('.')[0]
value=''
if triggered_input == 'default_neighborhood':
value = DEFAULT_NEIGHBORHOODS[city]
return dcc.Dropdown(
id='neighborhood',
value=value,
options=[{'label': v, 'value': v} for v in neighborhoods],
multi=False,
persistence_type='session',
persistence=city
)
@app.callback(
Output('persisted-choices', 'children'),
[Input('persisted-city', 'value'),
Input('neighborhood', 'value')]
)
def set_out(city, neighborhood):
return 'You chose: {}, {}'.format(neighborhood, city)
if __name__ == '__main__':
app.run_server(debug=True)