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?
I had the same problem last week, and even tried to achieve the disabled button behavior using Javascript, but eventually gave up. I've seen seen this discussed on the plotly forums, and there is clearly a need for this type of functionality, but I don't think it can be achieved easily in the current version.
One thing that is possible though, and is mentioned as a temporary solution by the Dash developer, is adding a global loading screen. In short, you need to add the following CSS to your stylesheet:
@keyframes fadein {
0% {
opacity: 0;
}
100% {
opacity: 0.5;
}
}
._dash-loading-callback {
font-family: sans-serif;
padding-top: 50px;
color: rgb(90, 90, 90);
/* The banner */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
cursor: progress;
opacity: 0;
background-color: rgb(250, 250, 250);
/* Delay animation by 1s to prevent flashing
and smoothly transition the animation over 0.5s
*/
-moz-animation: fadein 0.5s ease-in 1s forwards; /* Firefox */
-webkit-animation: fadein 0.5s ease-in 1s forwards; /* Safari and Chrome */
-o-animation: fadein 0.5s ease-in 1s forwards; /* Opera */
animation: fadein 0.5s ease-in 1s forwards;
}
A few clarifications:
_dash-loading-callback
selector selects a div which is added at the end of the body element each time a callback is made, and is removed when it is finished._dash-loading-callback
.Updates 2022
_dash-loading-callback
to _dash-loading
in newer versions. I didn't get the chance to test this yet.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With