Please see Chapter 08-MultiPageDashApp for an introduction to the Multi-Page Dash App Plugin
If you would like to add an example, feel free to create a pull request!
This example shows how dl.plugins.register_page
handles
- Using Nested folders in
pages/
- Storing icons as arbitrary keyword arguments
See the code in /demos/multi-page-nested-folders
In larger multi-page apps it's common to organize topics into categories. Each category may have its own folder with multiple
pages. This plugin automatically searches all subdirectories in pages/
and includes all the apps.
In our example the heatmaps.py
is in pages/
and pie-chart.py
is in pages/chapter/
.
The dash.page_registry
dictionary will include the subdirectory name(s) in the dict key and the module and path like this:
OrderedDict([
('pages.heatmaps', {
'module': 'pages.heatmap',
'path': '/heatmap',
...
}
),
('pages.chapter.pie-chart', {
'module': 'pages.chapter.pie-chart',
'path': '/chapter/pie-chart',
...
}
),
...
])
In this example app, we will create a sidebar nav for the app pages located in the chapter/
folder. We use a dbc.Offcanvas()
component and open the sidebar nav with a button.
Here is the app.py
import dash
from dash import dcc, html, Output, Input, State
import dash_labs as dl
import dash_bootstrap_components as dbc
app = dash.Dash(
__name__,
plugins=[dl.plugins.pages],
external_stylesheets=[dbc.themes.BOOTSTRAP, dbc.icons.FONT_AWESOME],
)
navbar = dbc.NavbarSimple(
dbc.DropdownMenu(
[
dbc.DropdownMenuItem(page["name"], href=page["path"])
for page in dash.page_registry.values()
if not page["path"].startswith("/chapter")
],
nav=True,
label="More Pages",
),
brand="Multi Page App Plugin Demo",
color="primary",
dark=True,
className="mb-2",
)
sidebar_button = dbc.Button(html.I(className="fa fa-bars"), id="sidebar-btn")
sidebar = dbc.Offcanvas(
dbc.Nav(
[html.H3("Chapters")]
+ [
dbc.NavLink(
[
html.I(className=page["icon"]),
html.Span(page["name"], className="ms-2"),
],
href=page["path"],
active="exact",
)
for page in dash.page_registry.values()
if page["path"].startswith("/chapter")
],
vertical=True,
pills=True,
),
id="offcanvas",
)
app.layout = dbc.Container(
[
navbar,
dbc.Row(
[
dbc.Col([sidebar_button], width=1),
dbc.Col([sidebar, dl.plugins.page_container]),
]
),
],
fluid=True,
)
@app.callback(
Output("offcanvas", "is_open"),
Input("sidebar-btn", "n_clicks"),
State("offcanvas", "is_open"),
)
def toggle_theme_offcanvas(n1, is_open):
if n1:
return not is_open
return is_open
if __name__ == "__main__":
app.run_server(debug=True)
Recall from the previous chapter that dl.plugins.register_page
also accepts arbitrary keyword arguments. We use this
feature to store the icon used in the nav for each page.
Here is how we store the FontAwesome icon for pages/chapter/pie-chart.py
dl.plugins.register_page(__name__, icon="fas fa-chart-pie")
You can see how the icon is included in the sidebar navigation: