I’ve had a lot of fun building a dashboard using Dash! I have run across a problem that I hope has a solution within Dash, although reading about similar users’ related problems I’m not sure.
Suppose I have two components (e.g. Slider, Dropdown, or Input) whose values are related. When I change the value of one, I want the other to change, and vice versa. This creates an obvious cyclic dependency, but this seems like something that should be accomplishable. Is it?
From a UI perspective, this can often be worked around, but I can think of cases where the natural inputs for a user have an interdependency. Suppose a user wants two dropdowns to select a city and chain restaurants. When they select a city, the restaurant dropdown should be populated by restaurants in that city, and when they select a restaurant, the city dropdown should be populated by cities that have that restaurant.
Here is a MWE with two Input components:
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash()
server = app.server
# define the layout of the dashboard
app.layout = html.Div([
html.Div([
html.H6('x'),
dcc.Input(id='input_x'),
], className='row'),
html.Div([
html.H6('2x'),
dcc.Input(id='input_2x'),
], className='row'),
])
# NOTE: This breaks because of a cyclic dependency
# not clear what can be done here.
# update input_x when input_2x changes
@app.callback(
Output('input_x', 'value'),
[Input('input_2x', 'value')]
)
def update_x(v):
return v/2
# update input_2x when input_x changes
@app.callback(
Output('input_2x', 'value'),
[Input('input_x', 'value')]
)
def update_2x(v):
return 2*v
app.css.append_css({'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'})
if __name__ == '__main__':
app.run_server()
I don’t know that there’s any workaround other than changing the UI to work differently.
I wonder also if there might be usability issues with this UI. If a user has selected a city, then the other drop down will be filtered to chains with restaurants in that city. Now if a user want’s to then select a specific chain, if it doesn’t occur in that city they selected, they then have to go and clear the city in the other dropdown before the desired chain will be available. In this case it seems like undesirable coupling between them; the filtering that might be a convenience in some contexts is now a friction point. And if the user isn’t fully aware of what’s going on with the filtering, they may incorrectly conclude that the desired chain is just not in the database.
Yeah, this isn’t possible right now. But, it’s a valid concern. Here’s a classic example where this would be useful: a slider is synced up with the text input:
This will be quite a bit of work to support correctly. If any organization or company has the software budget to sponsor this work, please reach out: https://plot.ly/dash/pricing
I thought I could break the cycle by using raise PreventUpdate when I can assert that the two inputs (box and slider) are synced with each other. However it looks like the rendered throws an error when it detects a cycle.
Perhaps a short term solution is to allow a way to explicitly disable the cycle checking (as in “trust me”, akin to supress_callback_exceptions) ?
Update
I dived into dash-renderer, and it looks like the error for circular dependencies is thrown from createDFS from dependecy-graph. Fortunately, the more recent version of that library introduced a “circular” argument exactly to prevent that error from being thrown.
I forked dash-renderer to allow for this error to be disabled (diff here)
Happy to do a PR if this is something useful to others, although I’d probably need help with figuring out how to make the parameter configurable more upstream.
Thanks! Could you at least create an issue in dash-renderer and a link to your code? We can help coach you through a PR, but the dash-renderer ones are usually very involved. We’ll get to this eventually though, and it’d be helpful to see some progress on it
Even I was struck with the same problem using two drop downs. My requirement is to update one drop-down using other drop-down value and vice-versa. Do we have any way to do this? If so give me a small example to do this. If we don’t have please let me know.
Was a solution to this scenario ever implemented? I’m running into this exact issue. I have a drop down and a url that I would like to match when one or the other changes.
What I am trying to do is having three dropdowns as input, and upon selection of a value in drop-down1, the options in drop-down 2 and dropdown3 would be filtered to show only corresponding options from the data frame for the other drop-downs.
I don’t know if this has been implemented, I have seen dependent drop-downs where the first drop down determines the options in the second drop-down.
I want a solution where either of the two drop-down can update the value of the other and vice-versa. I am looking forward to your help.