Search code examples
pythonflaskplotlyplotly-dashplotly-python

How to add/create a custom loader with Dash plotly?


I want to pass my gif to the loader component instead of using the default figures. Does anybody know how to do that?

This is my code :

dcc.Loading(
    id="loading-1",
    type="default",
    children=html.Div(id="loading-output-1"),
)

and I am trying to accomplish something like this :

dcc.Loading(
    id="loading-1",
    type="assets/dashboard_loader.gif",
    children=html.Div(id="loading-output-1"),
)

Can somebody please guide me ?


Solution

  • The type property specifies what the spinner looks like, but is limited to a set of values dash core components provides:

    type (a value equal to: 'graph', 'cube', 'circle', 'dot', 'default'; default 'default'): Property that determines which spinner to show one of 'graph', 'cube', 'circle', 'dot', or 'default'.

    So your approach is currently not possible, but there is a workaround.

    The html structure of the default spinner looks something like this:

    <div class="dash-spinner dash-default-spinner">
      <div class="dash-default-spinner-rect1"></div>
      <div class="dash-default-spinner-rect2"></div>
      <div class="dash-default-spinner-rect3"></div>
      <div class="dash-default-spinner-rect4"></div>
      <div class="dash-default-spinner-rect5"></div>
    </div>
    

    Each of these rectangle divs inside .dash-spinner are used for the default type animation. We don't care about these rectangles or anything that's inside of .dash-spinner, because we only want the gif animation.

    So what we could do here is to hide all .dash-spinner children and add an animated background to .dash-spinner.

    We can do so with css

    .dash-spinner {
      background-image: url("https://i.sstatic.net/SBv4T.gif");
      background-size: contain;
      background-repeat: no-repeat;
    }
    
    .dash-spinner * {
      display: none !important;
    }
    

    For including css see the documentation here.

    Minimal and reproducible example based on the example given in the documentation here:

    from dash import Dash
    import time
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output
    
    
    app = Dash(__name__)
    app.layout = html.Div(
        children=[
            html.H3("Edit text input to see loading state"),
            dcc.Input(id="loading-input-1", value="Input triggers local spinner"),
            dcc.Loading(
                id="loading-1", type="default", children=html.Div(id="loading-output-1")
            ),
        ],
    )
    
    
    @app.callback(
        Output("loading-output-1", "children"),
        Input("loading-input-1", "value"),
        prevent_initial_call=True,
    )
    def input_triggers_spinner(value):
        time.sleep(2)
        return value
    
    
    if __name__ == "__main__":
        app.run_server()
    

    Gif was taken from this related answer here.