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.