How to re-use drop-down lists

I’m building a web-app that has a navigation bar at the top.

Link 1
Link 2
Link 3
etc…

In each of these links, I would like to re-use the same drop-down lists. Each link has a different pandas dataframe but they can all be filtered the same way.

When I try re-using the same drop-down list across links (app1.py and app2.py), it automatically tries to trigger the call backs from the other application. Do I have to re-name the drop-down lists across apps? This seems inefficient.

I had a similar situation and a similar issue. While I’m sure others with more knowledge can give a proper answer, here’s what I did:

def get_dropdown_div(which):
    return html.Div(
        id=f"{which}-dropdown-div",
        children=[
            dcc.Dropdown(
                id=f"{which}-dropdown",
                value=default,
                options=[
                    {"label": i, "value": i} for i in ("default", "option2", "option3")
                ],
                clearable=False,
            ),
        ],
    )

def dropdown_handle(value):
    # do processing / configurations that's needed
    return result


[ ...] # app layout etc.


# *------------------*
# | Link 1 callbacks |
# *------------------*

@app.callback(
    Output("link1-graph", "figure"),
    [Input("link1-dropdown", "value")],
def update_link1_graph(value):
    return dropdown_handle(value)

# *------------------*
# | Link 2 callbacks |
# *------------------*

@app.callback(
    Output("link2-graph", "figure"),
    [Input("link2-dropdown", "value")],
def update_link2_graph(value):
    return dropdown_handle(value)

Some notes: Here I am using f-strings, a feature introduced in python 3.6 (I recommend the Realpython article for the interested). Of course, any string formatter will do. Also, in my case, I have a single app, and I define id for the div containing my dropdown (and similar for other elements to) so that I can hide them (a callback with Output("container-div", "style") returning {"display": "none"}), and show the appropriate options when the user is switching “links” (in my case selecting a value on a unique dropdown). I did it this way to avoid all versions processing when the user uses the dropdown, and to keep the previous state of the configurations when switching back and forth.

Now, it is not the prettiest, but by making a function to get the html for the dropdown, as well as a function for any processing that might be needed, the repeated code is at least minimized. But I would like to find a better way to do this, maybe by using closures or something. I’m sure there exists good examples somewhere on how to best handle these sort of situations.

To answer your question though, you can’t have one drop-down shared between multiple links that doesn’t fire for all the tabs sharing that dropdown. You could introduce logic, like including [State("current-link", "value")] and then have a if-statement that processes the filtering etc. appropriately, but this will make a large callback with many inputs, many outputs, and many states, since you need to serve all outputs defined each time. If there is only one output shared between all the different links, only the underlying data or something is different, then it should work fine. However, in this case, I would perhaps just have a dropdown to select the active dataframe rather than separate navigation links for each.

I hope I have been of some help, I’m fairly new to all this myself :sweat_smile:

Thanks for sharing. I actually figured out what I was doing wrong…

For the URL links, I was not using dcc.Link but rather simple htmt.A tags. Not sure why I set it up this way originally, but this made each link “refresh” the whole page thus resetting the drop-down values.

However once I swapped the links to use dcc.Link, it no longer triggers a web page refresh but rather, just a layout callback thus keeping my drop-down values.