📣 Loading states and Loading component

Hello Dash community :wave:

Update! This is now released in 0.39.0: 📣 Dash 0.39.0 released

We’ve released a new version of the previously announced Loading component (in this thread here and we would love your feedback! In this new version, you have two ways of displaying a spinner when a component is busy loading. The first option is the Loading component in dash_core_components, which acts as a wrapper that looks at its children components to see if any are loading. Here’s a small example:

# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.graph_objs as go
import time

from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

app.scripts.config.serve_locally = True

app.layout = html.Div(
    children=[
        dcc.Loading(id="loading-1", children=[html.Div(id="output-1")], type="default"),
        dcc.Input(id="input-1", value='Input triggers local spinner'),
        html.Div(
            [
                dcc.Loading(
                    id="loading-2",
                    children=[html.Div([html.Div(id="output-2")])],
                    type="circle",
                ),
                dcc.Input(id="input-2", value='Input triggers nested spinner'),
            ]
        ),
    ],
)

@app.callback(Output("output-1", "children"), [Input("input-1", "value")])
def input_triggers_spinner(value):
    time.sleep(1)
    return value


@app.callback(Output("output-2", "children"), [Input("input-2", "value")])
def input_triggers_nested(value):
    time.sleep(1)
    return value


if __name__ == "__main__":
    app.run_server(debug=False)

The other way is to target a new HTML data attribute that we now set on all of our components (including dash_html_components). You won’t need to use the Loading component this way, but you would need to supply your own CSS. Your layout could look like this:

# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.graph_objs as go
import time

from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

app.scripts.config.serve_locally = True

app.layout = html.Div(
    children=[
        html.Div(id="output-1"),
        dcc.Input(id="input-1", value="Input triggers local spinner"),
        html.Div(
            [
                html.Div(id="output-2"),
                dcc.Input(id="input-2", value="Input triggers nested spinner"),
            ]
        ),
    ]
)


@app.callback(Output("output-1", "children"), [Input("input-1", "value")])
def input_triggers_spinner(value):
    time.sleep(1)
    return value


@app.callback(Output("output-2", "children"), [Input("input-2", "value")])
def input_triggers_nested(value):
    time.sleep(1)
    return value


if __name__ == "__main__":
    app.run_server(debug=False)

And you can target the new data-dash-is-loading["true"] data attribute in a custom CSS file (here are the docs on how to do that ) like so:

*[data-dash-is-loading="true"]{
    visibility: hidden;
}
*[data-dash-is-loading="true"]::before{
    content: "Loading...";
    display: inline-block;
    color: magenta;
    visibility: visible;
}

You can start using this with Dash 0.39.0:

pip install dash==0.39.0

As always, your feedback is greatly appreciated!

I’m a big fan of this new dcc.Loading!

Coming to Dash as mostly a Python back-end developer any time I can prototype something and not worry about CSS until later it really reduces the cognitive burden of starting.

Quick question though, once comfortable with it will I be able to provide custom styles of the loading via the props of the dcc.Loading? I suspect not but just curious.

Thanks! You could definitely style the spinners the way you want, since they have CSS classes on them - so targeting those in a CSS file would override the default styles. Definitely something we’ll add to the documentation. In the future, it would also definitely be cool if a user could supply their own spinners to be used by the Loading component!

Hi there seems to be a problem installing the dash==0.37.0rc2 due to a missing dependency:

Could not find a version that satisfies the requirement dash-core-components==0.44.0rc3

Would gladly try this out if this gets resolved. Thanks.

@c_f Seems like the latest dash-core-components release candidate was released under 0.43.0rc3, not 0.44.0rc3. Uploaded the correct version of dcc. There’s another problem in the renderer that will prevent this RC to work when serve_locally=true is not set.

Can you try again? Sorry for the inconvenience!

Thanks I’ll try again soon. I usually have serve_locally=true set.

Sorry about that - the correct version is uploaded now as @Marc-Andre mentioned (thanks!). The other problem mentioned above wasn’t actually a problem - it should all work as expected, regardless of serve_locally=true.

I’m on Windows and I’ve installed:

dash==0.37.0rc2
dash-core-components==0.43.0rc3
dash-html-components==0.14.0rc21
dash-renderer==0.18.0rc4

This installed plotly 3.6.1

However, when I try to run the example, I get a file not found error:

FileNotFoundError: [WinError 2] The system cannot find the file specified 'C:\\Users\\....\\lib\\site-packages\\dash_core_components\\plotly-1.44.1.min.js'

Do I still not have the correct versions installed or am I running into something else?

(I’m using virtualenv to create my virtual environment.)

Nevermind. I re-read the thread and now see that I misunderstood the above post. Loading states requires dash-core-components==0.44.0rc3 .

So for anyone new to this, the required components are:

dash==0.37.0rc2
dash_html_components==0.14.0rc21
dash-core-components==0.44.0rc3

Very nice job with this! It is enhancements like this that give Dash a huge edge over some of the other vendors like Tableau, Qlik, PowerBI, etc.

Hi there.

Great job!

Now, how can we create new “loading components” that would be render inside the dcc.Loading wrapper? I don’t mean just styling them with css, but display our own defined html, or eventually even react/js in case we want to. The react option is not so important for us, but the html one it is.

Hello!
I am trying to use the Loading components while a graph is updating this way:

html.Div(children=[dcc.Loading(id='loading-1',
                                           children=html.Div(dcc.Graph(id=dcc_ids['cumulative_performance']),
                                                             className='chart_div'),
                                           type='spinner')]),

With the corresponding callback being:

@dash_app.callback(
    Output('cumulative_performance', "children"),
    [Input('param1', 'value'),
     Input('param2', 'value'),
     Input('param3', 'value'),
     ])
def my_function(param1, param2, param3):

I do see the spinner and that is so great but my chart never displays… I am probably doing something wrong…

Could you assist please??

NB: I am a huge Dash fan and take the opportunity to thank you for this framework !!

Cheers

Hi!

It is pretty! Thank you!

Is there a way to use loading_state property as callback input?
Problem:
I have a custom spinner (similar to the one here. I would like to show it depending on loading_state.is_loading and the state of the background task at the same time.

Cheers

Loading component does not render on first load if using dcc.Location.
See https://github.com/plotly/dash-core-components/issues/488

Hi all, trying to use the loading component for the first time, but I haven’t quite got it working yet. my layout and callback are as follows:

dcc.Loading(
    id="loading-1",
    children=[html.Div([dcc.Graph(id='themes-plot',
                                  figure = data_plots.empty_plot())
                                ],
                                style ={'width': '84%'}
                                )],
    type="default"),


@app.callback(Output("themes-plot", "children"), [Input('submit-button', "value")])
def input_triggers_spinner(value):
    time.sleep(1)
    return value

When you click the submit-button data a callback runs to filter and process the data which is then displayed in the themes-plot graph. Initially the graph displays and empty plot until updated by the callback, which takes a few seconds.

The above appears to display everything correctly and the graph updates correctly, but no spinner appears.

Could this be related to the fact that there is already a call back outputting to the themes-plot component?

Thanks!

Hi,

After trying again and re-writing the code it finally works for me:
The div below includes the chart and a parameter for the chart.
The other parameters are inherited from a tab component.

html.Div([
            dcc.Loading(id='loading-1',
                        children=[html.Div(dcc.Graph(id='chart_id'),
                                           className='chart_div') #custom css class
                                  ],
                        type='spinner'),
            dcc.RadioItems(
                options=[
                    {'label': 'l1', 'value': 'v1'},
                    {'label': 'l2', 'value': 'v2'},
                    {'label': 'l3', 'value': 'v3'},
                    {'label': 'l4', 'value': 'v4'},
                    {'label': 'l5', 'value': 'v5'},
                    {'label': 'l6', 'value': 'v6'},
                    {'label': 'l7', 'value': 'v7'}],
                value='v7',
                id='input3',
            ),
        ],
            className='seven columns',
            style={"padding-left": '20'}
        ),], 
           className='row', 
)

@dash_app.callback(
Output('chart_id', "figure"),
[Input('input1', 'value'),
 Input('input2', 'value'),
 Input('input3', 'value'),
 ])
 def func(input1, input2, input3):

Hope this will help you,

Cheers

Hi,

Really like the feature! Awesome stuff. I was wondering if you could help me with an issue I’m having.

I’m currently working on a multi-page app. Here’s an example of the index page:

index.py

html.Div(
            [
                dcc.Location(id='url', refresh=False),
                html.Div(id="navigation_bar"),
                dcc.Dropdown(id = "options"), # users pick options which edit the query
                dcc.Loading(id="loading",children=[html.Div(id='page-content')])
            ]
        )

@app.callback(
    Output('page-content', 'children'),
    [Input('url', 'pathname')]
def update_page(pathname):
     if pathname == "dashboard":
            return dashboard_layout
     else:
            display another layout

The page-content div sets a new layout every time the url changes. Each layout has its own dropdowns, graphs, tabs, etc which are populated by data from a SQL query. The query is based on the option a user picks in the options dropdown. The data from the query is then stored in a flask-cache on Redis so that all the pages can access it.

When the layout first loads, it takes a long time because the query is expensive. Subsequent steps are very quick because the queried data comes from a cache.

My issue right now is that the spinner appears for inexpensive processes (like changing a tab or clicking a dropdown) after the first data load. I would prefer if the spinner displayed only on the first time the query is run as stored in the cache.

Is there a way for me to set a “spinner on first load” option? Or do you see a better way for me to do this?

Please let me know.
Thanks!

Hi @mdylan2

you could use the decorator @app.first_callback that is alread available above your expensive first callbacks.

Cheers,

Hi @PNhd

I’m a little unsure what you mean by @app.first_callback. Is that a Dash function?

@PNhd @mdylan2
Im facing the same issue… I want the load component only to be triggered by one input, and not whenever a change is being made on the page.

The thing is in the documentation (https://dash.plot.ly/dash-core-components/loading_component), load 1 is triggered by input one, and not both inputs… thats what id expect…

The question is, is it meant to be triggered whenever a change is made or is this some sort of bug?