Interdependent components

Hello,

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()
1 Like

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.

OK, thanks - I suspected that changing the UI is required.

You’re right that this example is not the best - perhaps there are generally friction points with this kind of interdependency.

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

2 Likes

I have this exact use case.

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 :slight_smile:

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.

were you able to achieve this… I have spent a vouple of days trying out to figure out this and yet I am still stalk

Hi @Lobaloba1 and welcome to the Dash community :slight_smile:

It’s now possible to synchronize components with the latest release of Dash. Be sure to upgrade to v 1.19.0

See the examples in the announcement of this release:
https://community.plotly.com/t/dash-1-19-0-circular-callbacks-drag-value-in-dcc-slider-close-button-in-dev-tools-dcc-graph-bug-fixes/

Or see the last 3 examples in this chapter of the dash-docs:: Advanced Callbacks | Dash for Python Documentation | Plotly.

If you have more question, please describe what you are trying to do in a little more detail, and someone is likely to help.

Thanks for the swift reply.

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.

Thanks

HI @Lobaloba1

I think see what you are trying to do, and that’s a different topic than this thread.

Could you please create a new topic, perhaps with the subject “chained callback with 3 dropdowns” and I can help you find a solution.

@AnnMarieW I will do just that now