'Spinner removed when using long_callback in Dash app

My app works fine when I use the regular Dash callback, but I am currently forced to use long_callback. In this case, my spinner (dcc.Loading) disappears almost instantly - although, ironically, this seems to be a really useful place for a spinner. I have tried to create a minimal example below.

Am I misusing the spinners or is this a bug?

import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
from dash.long_callback import DiskcacheLongCallbackManager

import diskcache
import time


cache = diskcache.Cache('./cache')
long_callback_manager = DiskcacheLongCallbackManager(cache)

app = dash.Dash(
    __name__,
    long_callback_manager=long_callback_manager,
)


app.layout = html.Div(children=[
    dcc.Slider(id='my_slider', min=1, max=10, step=1, value=5),
    dcc.Loading(
        html.Div(id='my_div', children=['Start']),
    ),
])


@app.long_callback(
    Output('my_div', 'children'),
    Input('my_slider', 'value'),
    interval=2000,
)
def update_div(slider_value):
    time.sleep(5)
    return f'Done loading: {slider_value}'


if __name__ == '__main__':
    app.run_server(debug=True)

I have tried to set the loading_state/is_loading property in the running argument of the long_callback, but I haven't succeeded. Maybe it's not a "setable" property?



Solution 1:[1]

Not sure if this is the solution you are looking for, but I have discovered a method that works with dash bootstrap components using the dbc.Spinner in conjunction with the running keyword argument of the long_callback.

First, create a div where you want the spinner to appear, give it a unique id name and set its children equal to None. For me, I used a dbc.Row(dbc.Col()) instead of a div, but it should work the same. Then you will need to set the running keyword argument of the long_callback to output a dbc.Spinner. The following code is currently working for me. I have removed a lot of code, so ignore the inputs, ouputs and lack of layout components. Pay attention to the running kwarg.

app.layout = dbc.Container(dbc.Row(dbc.Col(id='fs_spinner', children=None)))

@app.long_callback(
    output=(
        Output("full_search_predictions", "data"),
        Output("full_results_query", "data"),
    ),
    inputs=[
        Input("submit_button", "n_clicks"),
        Input("search_query", "value"),
    ],
    running=[
        (Output('fs_spinner', 'children'), dbc.Spinner(size='md'), None)
    ],
    interval=20000,
    prevent_initial_call=True,
)

Here is what is happening. When the the long_callback begins, it returns a dbc.Spinner() to the children component of the fs_spinner. Once the callback is complete, it then returns None to the children component of the fs_spinner, which removes the spinner from the screen.

Hope this helps!

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 Waleed Alfaris