Margaret
Margaret

Reputation: 5929

Plotly table in a Dash app flashes up a empty chart axis before loading fully

I am developing a Dash app which will display a large table of data. However, because the table is so large, it takes a while to load the first time the app is opened on a given run; while it is loading, an empty chart axis is shown instead.

While loading, it looks like this: enter image description here

This seems very jarring since the view changes entirely once the table itself loads. Once it's thought for a moment, this is what's shown instead:

enter image description here

Is there some way to stop the temporary chart appearing? Maybe do something like replace it with a temporary "We'll be with you in a moment!" kind of message?

If it's helpful, this is the code I used to produce the above screenshots:

import pandas as pd
import plotly.graph_objects as go
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

d = {
    'A scores': [100, 90, 80, 90],
    'B scores': [95, 85, 75, 95],
    'C scores': [75, 60, 65, 70]
}
df = pd.DataFrame(data=d)

def display_table(min_a_score=0):

    filtered_data = df[df['A scores'] >= min_a_score]

    fig = go.Figure(
        go.Table(
            header=dict(
                values=filtered_data.columns,
                align="left"
            ),
            cells=dict(
                values=[filtered_data[x].tolist() for x in filtered_data],
                align='left'
            )
        )
    )
    return fig

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Slider(
        id='score-slider',
        min=10,
        max=100,
        step=10,
        value=0,
        marks=dict(zip(range(0, 110, 10), [f"{x} marks" for x in range(0, 110, 10)])),
    ),
    dcc.Graph(id="scores-table")
])

@app.callback(
    Output("scores-table", "figure"),
    [Input("score-slider", "value")]
)
def display_filtered_table(min_a_score):
    fig = display_table(min_a_score)
    return fig

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

Upvotes: 2

Views: 2271

Answers (2)

r-beginners
r-beginners

Reputation: 35275

There may be a way to control the display of the initial graph, but if you set an empty graph and designate it as the initial graph, unnecessary graphs will not be displayed.

fig = go.Figure(data=[go.Table(
    header=dict(values=['A Scores', 'B Scores']),
    cells=dict(values=[[],[]])
)])

app.layout = html.Div([...
    dcc.Graph(id="scores-table", figure=fig)
 ])

Upvotes: 1

Margaret
Margaret

Reputation: 5929

On recommendation of a friend, I added a dcc.Loading() component wrapping the dcc.Graph() call.

That is, I replaced the line

dcc.Graph(id="scores-table")

in the app.layout bit with

dcc.Loading(
    id="loading-1",
    children=[dcc.Graph(id="scores-table")],
    type="circle"
)

This means that instead of showing the empty axes, it shows a rotating circle suggesting progress is happening:

enter image description here

Upvotes: 2

Related Questions