Hello, I have the following Dash app whose layout is dependent of the data it gets initially,
if __name__ == '__main__':
path = "/mypath/"
data_manager.load_all_data(path)
app.layout = get_layout
app.run_server(debug=False, use_reloader=False)
and the paths and layouts are then created dynamically based on the data as we can see in the generate_sub_menus and render_page_content_callback
from mainwrapper import app
def generate_sub_menus():
reports = data_manager.get_full_df()
all_menus = []
for report in reports:
tab_links = []
for tab_page in reports[report]:
tab_links.append(dbc.NavLink(tab_page, href=f"/{report}/{tab_page}",
id={"type": "nav_link", "report_name": report, "tab_page": tab_page}))
menu = [
html.Li(
dbc.Row(
[
dbc.Col(report.capitalize()),
dbc.Col(
html.I(className="fas fa-chevron-right"),
width="auto",
),
],
className="my-2",
),
style={"cursor": "pointer"},
id={"type": "submenu-toggle", "report_name": report},
),
dbc.Collapse(
children=tab_links,
id={"type": "submenu-collapse", "report_name": report},
)
]
all_menus = all_menus + menu
return all_menus
def get_sidebar():
return html.Div(
[
html.Div(
[
html.H2("Report", style={"color": "black"}),
],
className="sidebar-header",
),
html.Br(),
html.Div(style={"border-top": "2px solid black"}),
html.Br(),
# nav component
dbc.Nav(generate_sub_menus(), vertical=True),
],
style=SIDEBAR_STYLE,
id="sidebar",
)
def get_layout():
return html.Div(
[
get_sidebar(),
html.Div(
className="content",
style=CONTENT_STYLE,
id="page-content",
),
dcc.Location(id="url"),
# dcc.Store(id='tables-store'), # CACHING ATTEMPT
]
)
@app.callback(
Output({'type': 'submenu-collapse', 'report_name': MATCH}, 'is_open'),
[Input({'type': 'submenu-toggle', 'report_name': MATCH}, 'n_clicks')],
[State({'type': 'submenu-collapse', 'report_name': MATCH}, 'is_open')],
)
def toggle_collapse(n, is_open):
if n:
return not is_open
return is_open
@app.callback(
Output({'type': 'submenu-toggle', 'report_name': MATCH}, 'className'),
[Input({'type': 'submenu-collapse', 'report_name': MATCH}, 'is_open')],
)
def set_navitem_class(is_open):
if is_open:
return "open"
return ""
@app.callback(Output("page-content", "children"), [Input("url", "pathname")],
prevent_initial_call=True)
def render_page_content(pathname):
full_df = data_manager.get_full_df()
if pathname and pathname.startswith("/"):
pathname = pathname[1:]
path_segments = pathname.split('/')
if pathname == "/":
first_report = next(iter(full_df))
first_tab = next(iter(full_df[first_report]))
return tab_page.tab_page_layout(first_report, first_tab)
return tab_page.tab_page_layout(path_segments[0], path_segments[1])
The thing is that if I do for example
app.layout = html.Div(
[
get_sidebar(),
html.Div(
className="content",
style=CONTENT_STYLE,
id="page-content",
),
dcc.Location(id="url"),
# dcc.Store(id='tables-store'), # CACHING ATTEMPT
]
)
Then the the sidebar will be empty as it seems the data wont be loaded and generate_sub_menus will then get empty data.
The page content will be display though.
I know that with the latter, the dash layout is computed once and if I serve the app.layout with a function like the first way, then it will be dynamic, but I dont understand why in the non-function way the data is not loaded when its literally the first thing the program does in its entry point. Also I must add that I have another file called mainwrapper.py where i import the app, as you can see