I am currently working on a multi-page application and have a question regarding the structure and definition of app.layout
.
I understand that in a multi-page app, individual page layouts are defined in separate files and can be returned as functions. My question is about the main app.layout
in app.py
.
Is it possible to define app.layout
as a function, and if so, can this function accept keyword arguments (**kwargs)? I have common components (dropdowns) in my app.layout that are same for all the pages. I would like to pass some kwargs to those components. Is this possible to achieve somehow?
Alternative is passing the same components into layout of each page but this is slower, harder to maintain, less readable etc.
Hi @davzup89
I don’t think that’s supported in dash. However, you can update the common components in the app.layout with a callback.
I noticed however that callbacks with _pages_location would only work in case if **kwargs are passed to layout.
@callback(
Output("dropdown", "value"),
Input('_pages_location', 'search'),
prevent_initial_call=False
)
Hi @davzup89
Pages has a built-in utility that converts the dcc.Location
search
prop to a nice Python dict and pass it to a page layout function.
To use the search prop to update a component in app.layout
you need to write your own utility.
When you run this example it, try adding a search to the url, and you will see the dropdown updates to show A
http://127.0.0.1:8050/?value=A
import dash
import dash_bootstrap_components as dbc
from dash import dcc, Input, Output, callback
from urllib.parse import parse_qs
app = dash.Dash(__name__, use_pages=True, external_stylesheets=[dbc.themes.BOOTSTRAP])
def parse_query_string(search):
"""
parse url query string
example: converts "?city=NY&country=USA" to {"city":"NY", "country":"USA"}
"""
if search and len(search) > 0 and search[0] == "?":
search = search[1:]
else:
return {}
parsed_qs = {}
for (k, v) in parse_qs(search).items():
v = v[0] if len(v) == 1 else v
parsed_qs[k] = v
return parsed_qs
navbar = dbc.NavbarSimple(
dbc.DropdownMenu(
[
dbc.DropdownMenuItem(page["name"], href=page["path"])
for page in dash.page_registry.values()
if page["module"] != "pages.not_found_404"
],
nav=True,
label="More Pages",
),
brand="Multi Page App Demo",
color="primary",
dark=True,
className="mb-2",
)
dropdown = dcc.Dropdown(["A", "B", "C"], id="common-dropdown")
app.layout = dbc.Container(
[navbar, dropdown, dash.page_container],
fluid=True,
)
@callback(
Output("common-dropdown", "value"),
Input('_pages_location', 'search'),
)
def update(seach):
parsed = parse_query_string(seach)
return parsed.get("value")
if __name__ == "__main__":
app.run_server(debug=True)
1 Like