Hi everyone,
I’m building an application that allows users to work with and update a dataset (id=‘src_data’) that is persistent across all pages within the Dash app. To do this I simply used a dcc.store + dynamically loaded page layout; while I can access the data across all pages, I’m unable to update the data at each page, in-fact, I don’t even get an indication that the callback has been triggered, I also end up in a quasi-infinite loading state. (quasi because I terminate it after 10-20 minutes)
My real code is a bit too bulky to post so I’ve recreated a simple snippet from the multipage app documentation that mirrors the fundamentals of what I’m trying to achieve. In theory, what I would like is for the src_data to be updated/appended whenever the user clicks on the submit button, present in both pages.
So in this example, user navigates to page 1 selects ‘SFO’ from the dropdown then hits submit resulting in src_data = [‘SFO’], user goes to page 2 hits submit on “YUL” resulting in src_data = [‘SFO’,‘YUL’] etc.
Could anyone provide me with some guidance? It would be greatly appreciated.
Thank you all!
Jon
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
# Since we're adding callbacks to elements that don't exist in the app.layout,
# Dash will raise an exception to warn us that we might be
# doing something wrong.
# In this case, we're adding the elements through a callback, so we can ignore
# the exception.
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content'),
dcc.Store(id='src_data',storage_type='session',data = [])
])
index_page = html.Div([
dcc.Link('Go to Page 1', href='/page-1'),
html.Br(),
dcc.Link('Go to Page 2', href='/page-2'),
])
page_1_layout = html.Div([
html.H1('Page 1'),
dcc.Dropdown(
id='page-1-dropdown',
options=[{'label': i, 'value': i} for i in ['SFO', 'JFK', 'LAX']],
value='LA'
),
html.Div(id='page-1-content'),
html.Button('Submit', id='p1_button'),
html.Br(),
dcc.Link('Go to Page 2', href='/page-2'),
html.Br(),
dcc.Link('Go back to home', href='/'),
])
@app.callback(Output('page-1-content', 'children'),
[Input('page-1-dropdown', 'value')],
[State('src_data', 'data')])
def page_1_dropdown(value,src):
return 'You have selected "{}"'.format(value)
page_2_layout = html.Div([
html.H1('Page 2'),
dcc.Dropdown(
id='page-2-dropdown',
options=[{'label': i, 'value': i} for i in ['ORD', 'YUL', 'HND']],
value='LA'),
html.Button('Submit', id='p2_button'),
html.Div(id='page-2-content'),
html.Br(),
dcc.Link('Go to Page 1', href='/page-1'),
html.Br(),
dcc.Link('Go back to home', href='/')
])
@app.callback(Output('page-2-content', 'children'),
[Input('page-2-dropdown', 'value')],
[State('src', 'value')])
def page_2_radios(value,src):
test = 'You have selected' + value + ' in page 2'
return test
@app.callback(Output('src_data', 'data'),
[Input('p1_button', 'n_clicks'),Input('p2_button', 'n_clicks')],
[State('src', 'data'),State('page-1-content', 'children'),State('page-2-content', 'children')])
def update_src(p1button,p2button,src,p1,p2):
print('triggered')
ctx = dash.callback_context
triggered = ctx.triggered[0]['prop_id']
data_list = src.copy()
if triggered == "p1_button.n_clicks":
data_list +=[p1]
elif triggered == "p1_button.n_clicks":
data_list +=[p2]
return data_list
# Update the index
@app.callback(dash.dependencies.Output('page-content', 'children'),
[dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/page-1':
return page_1_layout
elif pathname == '/page-2':
return page_2_layout
else:
return index_page
# You could also return a 404 "URL not found" page here
if __name__ == '__main__':
app.run_server(debug=True)