For multi-page apps, the structure we recommend can be roughly outlined as follows:
app.layout = html.Div([
# dash core components populating page contents,
html.Div(id='page-content')
])
Our examples usually focus around dcc.Location
, but these core components can be anything.
You’re right that there is no persistence across these different locations, because the page content is completely replaced whenever you click on another link.
The key is to take whatever dash core components you want to be persistance outside of page-content
. This works perfectly if your core components stay at the top, but to mimic your specfic architecture (a dcc in one page being accessed in another), you can simply add a callback that hides the content depending on which page you’re on.
Checkout this toy example that shows what this could look like. The experience of this app is that there is a dropdown on page 1, which is accessed on page 3:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
app.css.append_css({
'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'})
app.config.suppress_callback_exceptions = True
app.layout = html.Div([
# External dcc's for persistance
dcc.Location(id='url'),
dcc.Link('Page-1', href='/page1'),
dcc.Link('Page-2', href='/page2'),
dcc.Link('Page-3', href='/page3'),
# We want a dropdown in Page 1 to be persistant
html.Div([
html.H2(['Welcome to Page 1']),
dcc.Dropdown(
options=[
{'label': 'choice 1', 'value': 'choice 1'},
{'label': 'choice 2', 'value': 'choice 2'},
{'label': 'choice 3', 'value': 'choice 3'}
],
value='choice 1',
id='page-1-dropdown'
)
], id='external-page-1'),
# Page Content
html.Div(id='page-content')
])
# Define pages
page_1_content = html.Div([
html.P(['We are on page one now'])
])
page_2_content = html.Div([
html.H2(['Welcome to Page 2']),
html.P(['We are on page two '])
])
page_3_content = html.Div([
html.H2(['Welcome to Page 3']),
html.Div(id='dropdown-output'),
html.P(['We are on page three'])
])
# Callback to populate page-content
@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')]
)
def populate_content(url):
if url == '/page1':
return page_1_content
elif url == '/page2':
return page_2_content
elif url == '/page3':
return page_3_content
# Callback to hide Dropdown
@app.callback(
Output('external-page-1', 'style'),
[Input('url', 'pathname')]
)
def hide_external(url):
if url == '/page1':
return {'display': 'block'}
else:
return {'display': 'none'}
# Callback to show persistence: display dropdown contents from page 1 in page 3
@app.callback(
Output('dropdown-output', 'children'),
[Input('page-1-dropdown', 'value')]
)
def display_dropdown_contents(val):
return 'you have selected {}'.format(val)
if __name__ == '__main__':
app.run_server(debug=True)