Hi Dash users ,
I have noticed a modification of behavior when an app uses callbacks with “n_click” since the version 1.7 of Dash. Let’s take the code example after :
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions = True
menu = html.Aside([
html.Div("CLOSE", id='menu-mobile-close', n_clicks_timestamp=0),
html.Br(),
html.Br(),
dcc.Link('ZOne 1 and TEST 1', href='/zone1/test1', id="z1t1"),
html.Br(),
dcc.Link('ZOne 1 and TEST 2"', href='/zone1/test2', id="z1t2"),
html.Br(),
dcc.Link('ZOne 2 and TEST 2"', href='/zone2/test1', id="z2t2"),
html.Br(),
dcc.Link('ZOne 2 and TEST 2', href='/zone2/test2', id="z2t2"),
html.Br(),
], id='aside',
className="")
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div("OPEN SIDEBAR", style={"color": "red"}, id="menu-mobile-open", n_clicks_timestamp=0),
html.Div(id='page-content')
])
def get_search_bar(zone):
options = []
default_value = 0
if zone == "zone1":
options = [
{'label': 'New York City', 'value': 'NYC'},
{'label': 'Montreal', 'value': 'MTL'}
]
default_value = "NYC"
elif zone == "zone2":
options = [
{'label': 'Paris', 'value': 'PA'},
{'label': 'Toronto', 'value': 'TO'},
]
default_value = "PA"
search_bar = html.Nav(
children=html.Div(
children=[
html.Div(
children=[
dcc.Dropdown(
id='select-market-dropdown',
options=options,
value=default_value,
clearable=False,
className=""
)
]
)
]
)
)
return search_bar
@app.callback(dash.dependencies.Output('page-content', 'children'),
[dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
if pathname is not None:
selected_zone = pathname.split('/')[1]
search_bar = get_search_bar(selected_zone)
return html.Div([
menu,
search_bar,
html.Div(id="main_dashboard")])
return "home"
@app.callback(
Output(component_id='main_dashboard', component_property='children'),
[Input(component_id='select-market-dropdown', component_property='value')],
[State('url', 'pathname')]
)
def pick_market_in_dropdown(mkt, pathname):
if mkt == 'NYC' and pathname == "/zone1/test1":
return "NYC and zone1 and test 1"
elif mkt == 'NYC' and pathname == "/zone1/test2":
return "NYC and zone1 and test 2"
elif mkt == 'MTL' and pathname == "/zone1/test1":
return "MTL and zone1 and test 1"
elif mkt == 'MTL' and pathname == "/zone1/test2":
return "MTL and zone1 and test 2"
elif mkt == 'PA' and pathname == "/zone2/test1":
return "PA and zone2 and test 1"
elif mkt == 'PA' and pathname == "/zone2/test2":
return "PA and zone2 and test 2"
elif mkt == 'TO' and pathname == "/zone2/test1":
return "TO and zone2 and test 1"
elif mkt == 'TO' and pathname == "/zone2/test2":
return "TO and zone2 and test 2"
return mkt
@app.callback(
Output(component_id='aside', component_property='className'),
[Input(component_id='menu-mobile-open', component_property='n_clicks_timestamp'),
Input(component_id='menu-mobile-close', component_property='n_clicks_timestamp')]
)
def pick_market_layout(oclicked, cclicked):
if int(oclicked) > int(cclicked):
return 'app-sidebar '
elif int(cclicked) > int(oclicked):
return 'app-sidebar hide-sidebar'
else:
return 'app-sidebar hide-sidebar'
if __name__ == '__main__':
app.run_server(debug=True)
What this little app does is quite simple: the pathname changes the values inside a Dropdown, and the pathname + the dropdown value changes a text.
I have added 2 Div that have n_clicks_timestamp properties to change the className of html.Aside. Their purpose is to show the weird behavior.
With a dash version < 1.7, if I click on a link, then use the dropdown to select a city, then click on another link, the pick_market_in_dropdown()
callback is fired and I see in html.Div(id="main_dashboard")
the message that is supposed to appear.
However, when I use dash version 1.7 and do the exact same thing (click on a link, use the dropdown, then click on another link), nothing appears in the html.Div(id="main_dashboard")
. But if you comment the callback pick_market_layout
with the n_clicks_timestamp in Input, it works normally again.
I did not see anything referring to this king of new behavior in the changelog.
Does someone have an explanation? I would really appreciate, thanks!
Raphourbe