Black Lives Matter. Please consider donating to Black Girls Code today.

Updating graphs using a search dropdown feature

I’ve got the following application:

import dash
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
import numpy as np


app = dash.Dash()



np.random.seed(42)
random_x_1 = np.random.randint(1,101,100)
random_y_1 = np.random.randint(1,101,100)

random_x_2 = np.random.randint(1,101,100)
random_y_2 = np.random.randint(1,101,100)

random_x_3 = np.random.randint(1,101,100)
random_y_3 = np.random.randint(1,101,100)

random_x_4 = np.random.randint(1,101,100)
random_y_4 = np.random.randint(1,101,100)

options_1 = ["Option 1", "Option 2"]
options_2 = ["Option 3", "Option 4"]
search_options = ["Option 1", "Option 2", "Option 3", "Option 4"]


# Create a Dash layout
app.layout = html.Div([
    html.Div(
        html.H1('My Dashboard')
    ),
    html.Div([
        dcc.Dropdown(
            options=([{'label': i, 'value': i} for i in sorted(search_options)]),
            searchable=True,
            clearable=False,
            value='None',
            placeholder='Search for an option...',
            id='search-picker'
        )
    ]),
    dcc.Tabs(id="tabs", value='Tab1', children=[
        dcc.Tab(label='Tab 1', id='tab1', value='Tab1', children =[
            dcc.Graph(id='graph-1'),
            dcc.Dropdown(id='picker-1', options=([{'label': i, 'value': i} for i in sorted(options_1)]), value="Option 1"),
            html.Button('Apply', id='apply-btn-1', n_clicks=1),


        ]),

        dcc.Tab(label='Tab 2', id='tab2', value= 'Tab2', children=[
            dcc.Graph(id='graph-2'),
            dcc.Dropdown(id='picker-2', options=([{'label': i, 'value': i} for i in sorted(options_2)]), value="Option 3"),
            html.Button('Apply', id='apply-btn-2', n_clicks=0),


        ])
    ])
])


@app.callback(Output(component_id='search-picker', component_property='value'),
              [Input(component_id='apply-btn-1', component_property='n_clicks'),
               Input(component_id='apply-btn-2', component_property='n_clicks')],
              [State(component_id='search-picker', component_property='value')])
def clear_search(n_clicks_1, n_clicks_2, existing_state):
    if n_clicks_1 > 0:
        return None
    elif n_clicks_2 > 0:
        return None
    else:
        return existing_state


@app.callback(Output('graph-1', 'figure'),
              [Input('apply-btn-1', 'n_clicks')],
              [State('picker-1', 'value')])
def update_figure_1(n_clicks, selected):
    fig1 = {
        'data': [
            go.Scatter(
                x=random_x_1,
                y=random_y_1,

            )
        ],
        'layout': go.Layout(
            title='Random chart',
            height=500,
            xaxis=dict(
                title='Random x',
            ),
            yaxis=dict(
                title="Random y"
            ),
        )
    }

    fig2 = {
        'data': [
            go.Scatter(
                x=random_x_2,
                y=random_y_2,

            )
        ],
        'layout': go.Layout(
            title='Random chart',
            height=500,
            xaxis=dict(
                title='Random x',
            ),
            yaxis=dict(
                title="Random y"
            ),
        )
    }

    if selected == "Option 1":
        return fig1

    elif selected == "Option 2":
        return fig2

    else:
        return {}


@app.callback(Output('graph-2', 'figure'),
              [Input('apply-btn-2', 'n_clicks')],
              [State('picker-2', 'value')])
def update_figure_2(n_clicks, selected):
    fig1 = {
        'data': [
            go.Scatter(
                x=random_x_3,
                y=random_y_3,

            )
        ],
        'layout': go.Layout(
            title='Random chart',
            height=500,
            xaxis=dict(
                title='Random x',
            ),
            yaxis=dict(
                title="Random y"
            ),
        )
    }

    fig2 = {
        'data': [
            go.Scatter(
                x=random_x_4,
                y=random_y_4,

            )
        ],
        'layout': go.Layout(
            title='Random chart',
            height=500,
            xaxis=dict(
                title='Random x',
            ),
            yaxis=dict(
                title="Random y"
            ),
        )
    }

    if selected == "Option 3":
        return fig1

    elif selected == "Option 4":
        return fig2

    else:
        return {}


@app.callback(Output(component_id='picker-1', component_property='value'),
              [Input(component_id='search-picker', component_property='value')],
              [State(component_id='picker-1', component_property='value')])
def show_searched_option_1(selected, existing_state):
    if selected is None:
        return existing_state
    else:
        for x in options_1:
            if selected == x:
                return x
        for y in options_2:
            if selected == y:
                return existing_state


@app.callback(Output(component_id='picker-2', component_property='value'),
              [Input(component_id='search-picker', component_property='value')],
              [State(component_id='picker-2', component_property='value')])
def show_searched_option_2(selected, existing_state):
    if selected is None:
        return existing_state
    else:
        for x in options_2:
            if selected == x:
                return x
        for y in options_1:
            if selected == y:
                return existing_state


@app.callback(Output(component_id='tabs', component_property='value'),
              [Input(component_id='search-picker', component_property='value')],
              [State(component_id='tabs', component_property='value')])
def navigate_to_specific_tab(selected, existing_state):
    if selected is None:
        return existing_state
    else:
        for x in options_1:
            if selected == x:
                return "Tab1"
        for y in options_2:
            if selected == y:
                return "Tab2"


if __name__ == '__main__':
    app.run_server(debug=True)

There are two tabs and each of the tabs contains a graph and a dropdown. Each graph can be updated depending on the selected option from the dropdown by clicking on the “Apply” button. There’s also a search feature - it allows me to search for options in both tabs. For example, if I select “Option 4” from the search dropdown, I’m taken to Tab 2 where “Option 4” appears on the local dropdown. The problem is that I can only see the changes if I click on the apply button. I’ve been trying to make that change automatic but with no success.

I tried using the function below which sets the 'n_clicks" property of the apply button in the first tab to ‘1’ every time a new option is selected from the search dropdown but I get a loading dependencies error.

@app.callback(Output(component_id='apply-btn-1', component_property='n_clicks'),
              [Input(component_id='search-picker', component_property='value')],
              [State(component_id='apply-btn-1', component_property='n_clicks')])
def update_tab_1(selected, existing_state):
    if selected is None:
        return existing_state
    else:
        for x in options_1:
            if selected == x:
                return 1
        for y in options_2:
            if selected == y:
                return existing_state

Any idea what the problem might be or how I can achieve what I want in a different way? Any help would be appreciated. Thanks.