Is it possible to have multiple dcc.Location
elements in one application?
I have a multi-page dash application structured as follows:
app.py
pages
|-- reviewer.py
|-- admin.py
My app homepage has two dbc.NavLink
items - one for the “reviewer” and one for the “admin”. When the user clicks on “reviewer”, it links to the /reviewer
page. The content of the /reviewer
page are defined in reviewer.py
, which consists of a sidebar with links to new, different pages. When clicked on each of these new links, a different text is to be rendered in an html.Div
element defined in the /reviewer
page. I have one dcc.Location
item for my homepage to link to /render
and /admin
pages and another dcc.Location
item in the /reviewer
page to link to the sidebar pages. However, every time I click on a link on a sidebar item on the /reviewer
page, the callback function for the homepage’s dcc.Location
gets called even though the two dcc.Location
items have different id
s.
Is there a way to link to the sidebar items on the /reviewer
page from a dcc.Location
item defined in the /reviewer
page? I am trying not to use the homepage’s dcc.Location
item to link to the sidebar items to keep the logic of the /reviewer
page separate from the homepage’s logic. Below is my code.
Would appreciate any help, thanks!
app.py
:
import dash_bootstrap_components as dbc
from dash import html, dcc, callback
from dash_extensions.enrich import DashProxy, Input, Output, ServersideOutputTransform
from pages import reviewer
app = DashProxy(__name__, title='Dash App', external_stylesheets=[dbc.themes.BOOTSTRAP],
external_scripts=["https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"],
suppress_callback_exceptions=True, transforms=[ServersideOutputTransform()])
navbar = dbc.NavbarSimple(
brand="Dash App",
brand_href="#",
color="primary",
dark=True,
fluid=True,
sticky='top'
)
login_nav = html.Div([
navbar,
dbc.Nav([
dbc.NavItem(dbc.NavLink("Login as Reviewer", href='/reviewer')),
dbc.NavItem(dbc.NavLink("Login as Admin", href="/admin")),
],
vertical="md",
pills=True,
)
])
app.layout = html.Div([
dcc.Location(id='main-url', refresh=False),
html.Div(id='page-content-main'),
])
@callback(
Output('page-content-main', 'children'),
Input('main-url', 'pathname')
)
def display_page(pathname):
if pathname == "/":
return login_nav
elif pathname == '/reviewer':
return reviewer.layout
elif pathname == '/admin':
return html.P("Admin Page")
else:
return '404'
if __name__ == '__main__':
app.run_server(debug=True, port=8051)
reviwer.py
:
import dash_bootstrap_components as dbc
from dash import Input, Output, dcc, html, callback
SIDEBAR_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 1rem",
"background-color": "#f8f9fa",
}
CONTENT_STYLE = {
"margin-left": "18rem",
"margin-right": "2rem",
"padding": "2rem 1rem",
}
sidebar = html.Div(
[
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"A simple sidebar layout with navigation links", className="lead"
),
dbc.Nav(
[
dbc.NavLink("Page 0", href="/reviewer", active="exact"),
dbc.NavLink("Page 1", href="/reviewer/page-1", active="exact"),
dbc.NavLink("Page 2", href="/reviewer/page-2", active="exact"),
],
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
content = html.Div(id="page-content", style=CONTENT_STYLE)
layout = html.Div([dcc.Location(id="url"), sidebar, content])
@callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
if pathname == "/reviewer":
return html.P("This is the content of page 0!")
elif pathname == "/reviewer/page-1":
return html.P("This is the content of page 1. Yay!")
elif pathname == "/reviewer/page-2":
return html.P("Oh cool, this is page 2!")
return html.Div(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognised..."),
],
className="p-3 bg-light rounded-3",
)