'Display loading symbol while waiting for a result with plot.ly Dash
In my Dash-based application, a button triggers a long-running computation. Wouldn't it be nice to display a loading animation while the result is not yet there, and make the button inactive so it is not clicked again before the computation finishes?
I am using Bulma for UI design and wanted to use the button is-loading
CSS class for that purpose.
My first idea was to have two callbacks: One triggered by the button click to set the button to is-loading
, and one triggered by a change in the output to set it back to normal.
@app.callback(
Output('enter-button', 'className'),
[
Input('graph', 'figure')
],
)
def set_trend_enter_button_loading(figure_changed):
return "button is-large is-primary is-outlined"
@app.callback(
Output('enter-button', 'className'),
[
Input('enter-button', 'n_clicks')
],
)
def set_trend_enter_button_loading(n_clicks):
return "button is-large is-primary is-outlined is-loading"
Apparently it doesn't work that way:
dash.exceptions.CantHaveMultipleOutputs:
You have already assigned a callback to the output
with ID "enter-button" and property "className". An output can only have
a single callback function. Try combining your inputs and
callback functions together into one function.
Any ideas how to make this work?
Solution 1:[1]
Since dash-renderer==0.9.0, a div tag is added to your layout when your app is waiting for a callback. You can put a different css in it as suggested here by Chris: https://community.plot.ly/t/mega-dash-loading-states/5687
Also, a new feature is coming which fit your needs. It is currently in alpha version: https://community.plot.ly/t/loading-states-api-and-a-loading-component-prerelease/16406
Solution 2:[2]
Loader with custom GIF
Just create a folder named assets in the root of your app directory and include your CSS and JavaScript files in that folder. Dash will automatically serve all of the files that are included in this folder. By default the url to request the assets will be /assets but you can customize this with the assets_url_path argument to dash.Dash.
Create a customer css file under style folder
- app.py
- assets/
|-- loader.css
custom css
._dash-loading-callback {
position: fixed;
z-index: 100;
}
._dash-loading-callback::after {
content: 'Loading';
font-family: sans-serif;
padding-top: 50px;
color: #000;
-webkit-animation: fadein 0.5s ease-in 1s forwards; /* Safari, Chrome and Opera > 12.1 */
-moz-animation: fadein 0.5s ease-in 1s forwards; /* Firefox < 16 */
-ms-animation: fadein 0.5s ease-in 1s forwards; /* Internet Explorer */
-o-animation: fadein 0.5s ease-in 1s forwards; /* Opera < 12.1 */
animation: fadein 0.5s ease-in 1s forwards;
/* prevent flickering on every callback */
-webkit-animation-delay: 0.5s;
animation-delay: 0.5s;
/* The banner */
opacity: 0;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.5);
text-align: center;
cursor: progress;
z-index: 100000;
background-image: url(https://www.w3schools.com/html/programming.gif);
background-position: center center;
background-repeat: no-repeat;
}
@keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
/* Firefox < 16 */
@-moz-keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
/* Internet Explorer */
@-ms-keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
/* Opera < 12.1 */
@-o-keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | gustave toison |
Solution 2 | Anon30 |