We need to provide a better loading experience for Dash Apps. Many apps use callbacks that take several seconds to load and up until now, the only loading state that was available was in the document.title (the tab of your browser).
I’d like to make “loading states” a first-class citizen in Dash: customizable on the component-level as a JS component author or as a Dash app developer and customizable on the app-level (e.g. full-screen overlays).
I have just added preliminary support for app-level loading screens in dash-renderer==0.9.0. dash-renderer will now inject a <div class="_dash-loading-callback"/> into the app whenever it is waiting for a callback to be executed. This element is unstyled and contains no content. You can bind your own loading screens to this component by using custom CSS. Here’s an example of a grey loading screen that fades in (over 0.5s).
Upgraded my dash environment and tested this feature in my app. The user experience is quite good. But I found one issue as below:
OS: win10
Browser: Chrome and Edge
Screen Resolution: 1920x1080
Set scale to 150% in the display setting (right click in the desktop)
The result is that the 20% bottom part is still solid while in the loading state (see following picture)
Is there (or will there be) any functionality to only show the callback div when the callback lasts more than a specified amount of time? Its great for long callbacks but flashes up annoyingly for short callbacks!
That solution didn’t work for the spinner example I showed above, but if you fade in the spinner with enough delay the flicker goes away:
(updated css to include a delay)
@chriddyp I’m not quite sure I understood the support for loading screens. Once I install dash-renderer==0.9.0, it will give me an unstyled and empty screen while my callbacks are executed? I don’t want to append no customization right now, but it would be great to show somehow that the app is loading. I have different loading periods depending on the callback and some of them take up to 20 seconds to update. The user will probably break the application before that. Thanks again!
Did you try the example that I posted here? 📣 Dash Loading States That example contains a custom CSS file that is used to display an overlay while callbacks are loading. You can customize this CSS file to display the loading indicator in a separate way if you’d like, as was done by
@chriddyp Basically, I have multiple dropdowns filtering two tables. Depending on the dropdown I select it is going to take longer to update the tables. I’m failing to see how I’d use different loading indicators in this case…
This isn’t yet customizable on the component level, it’s only global. All we’re doing is:
So, that element will appear on every callback, there is no way to differentiate it between different callbacks.
It still is not yet possible to customize the loading experience on the per component level (“different loading indicators”). I’d like to add this functionality but it will be quite a bit of work, will likely need a company or organization to help sponsor the development of it (Consulting, Training & Open-Source Development)
All you need to do is adding app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/brPBPO.css"}). All the rest is already being managed for you. The screen will be shaded when the “Updating…” shows up in the document.title (the tab in the browser).
The spinner solution works great for me, thanks! I was wondering if there is a way to somehow customize the contents of the _dash-loading-callback element and not only the css?
For example what I’m looking for is to have the spinner and a “Loading” text displayed when a callback is running
Another example would be to have the background greyed out (with a 100% div) and display the spinner at the same time
I developed a codepen showcasing a small addition using CSS pseudo elements that enables embedding text and animated gifs into the Dash loading callback div.
The core idea is moving all the CSS in ._dash-loading-callback into the pseudo-element ._dash-loading-callback::after. The original class can be barebones: