Reputation: 123
While using plotly dash, I want to choose something from a dropdown on page 1, pass that value to page 2 (and filter some data on here), choose from a dropdown on page 2 and pass both values from page 1 and 2 to page 3 to filter some more data here.
I've tried using the Store but encounter a problem that "A nonexistent object was used as an "Input""
Any idea how I can pass data between more than two pages?
Upvotes: 1
Views: 2626
Reputation: 55
There has been an update on this problem with Dash version 2.9 in March 2023. They added a new option allow_duplicate
on the Output
element. It can be used as shown in the official example by Dash:
from dash import Dash, Input, Output, html, dcc, callback
import plotly.express as px
import plotly.graph_objects as go
app = Dash(__name__)
app.layout = html.Div([
html.Button('Draw Graph', id='draw-2'),
html.Button('Reset Graph', id='reset-2'),
dcc.Graph(id='duplicate-output-graph')
])
@callback(
Output('duplicate-output-graph', 'figure', allow_duplicate=True),
Input('draw-2', 'n_clicks'),
prevent_initial_call=True
)
def draw_graph(n_clicks):
df = px.data.iris()
return px.scatter(df, x=df.columns[0], y=df.columns[1])
@callback(
Output('duplicate-output-graph', 'figure'),
Input('reset-2', 'n_clicks'),
)
def reset_graph(input):
return go.Figure()
if __name__ == '__main__':
app.run(debug=True)
See how the example app looks like here: https://dash.plotly.com/duplicate-callback-outputs#setting-allow_duplicate-on-duplicate-outputs
The article also provides another way to solve the problem, but it might not be applicable in your case, because you are working on a multi page dash app.
Pay attention to this statement of the article:
Where you have multiple callbacks targeting the same output, and they both run at the same time, the order in which updates happen is not guaranteed. This may be an issue if you are updating the same part of the property from each callback. For example, a callback output that updates the entire figure and another one that updates the figure layout.
Upvotes: 1
Reputation: 1212
The dcc.Store
is the way to do this. I expect what you are doing wrong is that the Store is situated within one of your pages in your layout, hence when the page switches out you lose the store. What you need to do is create the store in the root of your layout, so that it is accessible from all the pages.
Here is a basic app_layout from a Bootstrap app I built to try to demonstrate what I mean:
app.layout = html.Div(
children=[
dcc.Store(id='some-data'),
dbc.Container(
id='root-content',
children=[
# Your actual app and its pages are within a container of some sort.
# In this case a Bootstrap container, but could also just be a div if
# you are not using Bootstrap. The key point is
# that the 'some-data' store is always in the layout,
# irrespective of which page is active.
],
),
])
Upvotes: 2