Hello All,
I was having an issue with wanting to display loading screens only when the pages_content was displaying. This is not possible with just a regularly wrapped loading of the page_container
, as this has an unexpected behavior of triggering any time a component is updated inside the layout.
Take this example:
app.py
import dash
from dash import Dash, html, dcc
import dash_bootstrap_components as dbc
app = Dash(__name__, use_pages=True)
sidebar = dbc.Nav(
[dbc.NavLink(pg['title'], href=pg['path']) for pg in dash.page_registry.values()]
)
app.layout = html.Div([sidebar, dcc.Loading(dash.page_container)])
if __name__ == '__main__':
app.run(debug=True)
home.py
import dash
from dash import dcc, html, callback, Output, Input
import time
dash.register_page(__name__, path='/', title='Home')
layout = html.Div(
[
'testing-home',
html.Button('button', id='test'),
html.Div(id='testDiv')
]
)
@callback(
Output('testDiv','children'),
Input('test', 'n_clicks')
)
def test(n1):
if n1:
time.sleep(2)
return 'testing'
return dash.no_update
Any time you click the button, you are greeted with this over the whole layout:
Obviously, this is very problematic for any time that you want to have a bunch of updates and callbacks manipulating things.
Here is a workaround that I really like for this, first, we alter the app like so (dls is a nice option, as you can show it initially):
import dash
from dash import Dash, html, dcc
import dash_bootstrap_components as dbc
import dash_loading_spinners as dls
app = Dash(__name__, use_pages=True)
sidebar = dbc.Nav(
[dbc.NavLink(pg['title'], href=pg['path']) for pg in dash.page_registry.values()]
)
app.layout = html.Div([sidebar, dash.page_container, dls.Hash(id='loading', show_initially=True, fullscreen=True)])
if __name__ == '__main__':
app.run(debug=True)
Next, add a style.css:
#loading {
display: none !important;
}
body:has(#_pages_content[data-dash-is-loading="true"]) #loading {
display: flex !important;
}
The result is that the overall loading screen only displays any time there is a change to the _pages_content
that involves a layout being changed and not changes within the layout.
Also, note, that your #loading
could be anything you want to display while loading the _pages_content
.