Loading and Spinners

Hello!

In my app, I currently have two pages. One is a home page where a user selects information. That information then goes to a SQL database and pulls info for page 2. It does take a few seconds to load the second page. Currently there is no indicator that anything is happening except “Updating…” on the tab.

How can I get either a spinner or honestly any kind of alert to show that the page is loading? I’ve looked at some previous topics but I’m still not understanding currently.

Thanks!

Hello @bpolasek,

The easiest way would be to actually wrap the page_container div in the loading spinner.

However, this would trigger the spinner for every component update, which would be annoying.

The other option, is to have the layout load without the initial data (as I am sure this is how you are loading it), then in a callback you populate the data. Wrapping page-2 or whatever element in the spinner would give your app the feedback desired.

Okay I got it to show for a second and then it stopped. Any thoughts? Here is my code for reference:

layout = dbc.Spinner(html.Div(id='graph', children=[]))

@callback(
    Output('graph', 'children'),
    Input('store', 'data')
)
def create_graph(data):
    df = pd.DataFrame(data['df'])
    df['Sign'] = np.where(df['DeviationValue'] > 0, 'Positive', 'Negative')
    fig = px.area(df, 
                  y='DeviationValue', 
                  title=f"Graph of {data['engine']} going back one year from {data['date']}",
                  color='Sign',
                  color_discrete_map={
                    'Positive': 'green',
                    'Negative': 'red'
                  },
                  labels={
                    "DeviationValue": 'Deviation',
                    'index': ''
                  })
    fig.update_traces(showlegend=False)
    for i in range(len(fig['data'])):
        fig['data'][i]['line']['width'] = 0

    fig2 = px.scatter(df, y='DeviationValue', opacity=0)

    fig3 = go.Figure(data=fig.data + fig2.data)

    df['SavGol'] = signal.savgol_filter(df['DeviationValue'], 576, 1)

    fig3.add_trace(go.Scatter(y=df['SavGol'], mode='lines', line=dict(color='black')))
    fig3.update_traces(showlegend=False)
    fig3.update_layout(template='presentation',
                       title_font_size=58,
                       title=f"Graph of {data['engine']} going back one year from {data['date']}"
                           )
    # fig3.update_xaxes(visible=False)
    # fig3.update_yaxes(range=[-10, 10])

    return dcc.Graph(figure=fig3)

Instead of wrapping the dcc.Graph in a div, try this:

layout = dbc.Spinner(dcc.Graph(id='graph'))

@callback(
    Output('graph', 'figure'),
    Input('store', 'data')
)
def create_graph(data):
    df = pd.DataFrame(data['df'])
    df['Sign'] = np.where(df['DeviationValue'] > 0, 'Positive', 'Negative')
    fig = px.area(df, 
                  y='DeviationValue', 
                  title=f"Graph of {data['engine']} going back one year from {data['date']}",
                  color='Sign',
                  color_discrete_map={
                    'Positive': 'green',
                    'Negative': 'red'
                  },
                  labels={
                    "DeviationValue": 'Deviation',
                    'index': ''
                  })
    fig.update_traces(showlegend=False)
    for i in range(len(fig['data'])):
        fig['data'][i]['line']['width'] = 0

    fig2 = px.scatter(df, y='DeviationValue', opacity=0)

    fig3 = go.Figure(data=fig.data + fig2.data)

    df['SavGol'] = signal.savgol_filter(df['DeviationValue'], 576, 1)

    fig3.add_trace(go.Scatter(y=df['SavGol'], mode='lines', line=dict(color='black')))
    fig3.update_traces(showlegend=False)
    fig3.update_layout(template='presentation',
                       title_font_size=58,
                       title=f"Graph of {data['engine']} going back one year from {data['date']}"
                           )
    # fig3.update_xaxes(visible=False)
    # fig3.update_yaxes(range=[-10, 10])

    return fig3

Same thing, still only showed for just a second :confused:

Part of the reason it’s taking a little bit is because it’s pulling data from a SQL database and then making that into a graph. So I’m not sure if that matters.

Use a function to refresh the data, and use it inside of the callback to refresh the df.

I’m not sure what you mean. Sorry this is all still fairly new to me!

The length of time it takes to show is because you are updating your data somehow to the dcc.Store.

Is there a possibility you could give an MRE:

I ended up getting it to work when I found this thread!

Thanks for all your help!

2 Likes

Yup, that is a workaround, I use something similar except with a window listener. :slight_smile:

2 Likes