Visual explanation for the title:
I want to change whatever is inside the navbar (there will be dropdown, sliders, radio items etc., in there, like this, but I don’t want to use FastDash like it’s used in this page) when I change pages, with the addiction that the navbar is collapsible and there is some persistence, that is, the navbar will share the same state (opened or closed) when I change pages.
I just copied the code from here to make the bar collapsible and adapted it to each page of the app.
Here is the code:
App.py
import dash
from dash import Dash, html, dcc, callback, Input, Output, State
import dash_mantine_components as dmc
app = Dash(__name__, use_pages=True)
server = app.server
page = list(dash.page_registry.values())
menu1 = dmc.Menu(
[
dmc.MenuTarget(dmc.Button('Pages')),
dmc.MenuDropdown(
[
dmc.MenuItem(
'Page 1',
href=page[0]['path'],
),
dmc.MenuItem(
'Page 2',
href=page[1]['path'],
),
]
)
]
)
navwidth = 1
#----------------------------------------------------------------------------------------------------
app.layout = \
html.Div(
children=[
dmc.Grid(
children=[
dmc.Col(
html.Div(
children=[
"Minimal working example"
],
style={'fontSize': 30, 'textAlign': 'left'}),
span='content', offset=2),
dmc.Col(menu1, span='content', offset=0),
]),
html.Hr(),
html.Div(
children=[
dash.page_container,
],
style={'position':'relative', 'top':5}
)
]
)
if __name__ == "__main__":
app.run(debug=True, port=8060)
Pg1.py
import dash
from dash import Dash, html, dcc, Input, Output, State, callback
import dash_mantine_components as dmc
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
dash.register_page(__name__, name='Page 1', path='/')
navwidth = 1
#----------------------------------------------------------------------------------------------------
layout = dmc.Container(
children=[
html.Div(id='nav-div',
children=[
dmc.Navbar(
id='sidebar',
fixed=False,
hidden=True,
width={"base": navwidth},
position='right',
children=[
'Page 1 navbar content \n 111111111'
],
style={
"overflow": "hidden",
"transition": "width 0.3s ease-in-out",
"background-color": "#f4f6f9",
},
),
]
),
dmc.Container(
children=[
dmc.Burger(id='sidebar-button'),
dmc.Container(
'Page 1 content'
),
],
size="100%",
p=0,
m=0,
style={"display": "flex", "maxWidth": "100vw", "overflow": "hidden",
"flexGrow": "1", "maxHeight": "100%", "flexDirection": "column"},
id="content-container"
),
],
size="100%",
p=0,
m=0,
style={"display": "flex", "maxWidth": "100vw", "overflow": "hidden", "maxHeight": "100vh",
"position": "absolute", "top": 0, "left": 0, "width": "100vw"},
id="overall-container"
)
#--------------------------------------------------------------------
@callback(
Output("sidebar", "width"),
Input("sidebar-button", "opened"),
State("sidebar", "width"),
prevent_initial_call=True,
)
def drawer_demo(opened, width):
if opened:
if width["base"] == navwidth:
return {"base": 200}
else:
return {"base": navwidth}
else:
if width["base"] == navwidth:
return {"base": 200}
else:
return {"base": navwidth}
if __name__ == '__main__':
app.run(debug=True)
Page 2 is basically the same, but I’ve changed some component id’s and some content from 1 to 2.
So I made what is shown in the gif by recreating this layout in each page, but I want to create this layout only in the main app and then change the sidebar’s content with dcc.Store
, but I don’t know how to use it to pass data to the Dmc.Navbar
’s children, I also tried creating an empty Html.Div
in the main app, in order to make it the Output of a callback in each page and returning a Navbar to it’s children, something like this:
@callback(
Output('html-div', 'children')
Input('Something exclusive to page X, 'Some property')
)
def return_navbar(property):
if property == "Something that ensure I'm in page X":
navbar = dmc.Navbar(
id='sidebarX',
fixed=False,
hidden=True,
width={"base": navwidth},
position='right',
children=[
'Page X navbar content \n XXXXXXXXX'
],
style={
"overflow": "hidden",
"transition": "width 0.3s ease-in-out",
"background-color": "#f4f6f9",
},
),
else:
navbar = ""
return navbar
I’m also avoiding creating the callbacks in the main page, because then I’d have to define all the items I want to go in the Navbar, for each page, in the main app and it’d make it very loaded, I just want to define the elements in each page and pass it to the Div in the main app.