dash
                                
                                 dash copied to clipboard
                                
                                    dash copied to clipboard
                            
                            
                            
                        Loading state not working correctly when layout is in a function
When investigating https://github.com/plotly/dash-core-components/issues/488 I noticed it does not only apply to using Location components, but rather happens when the Loading components are in a layout that comes from a function. Here's the same example code as from the issue above, but with an Input component instead of a Location component:
# -*- 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
import numpy as np
from dash.dependencies import Input, Output, State
app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.config['suppress_callback_exceptions']=True
app.layout = html.Div([
    dcc.Input(id='url'),
    dcc.Loading([html.Div(id='page-body')])
])
def make_layout(pathname):
    return html.Div([
    html.Div([
            dcc.Loading(
            id="loading-1",
            children=[html.Div(id='figure-container')],
            type="circle"),
            html.Button(id="input-1", children='Input triggers nested spinner')
        ], style={'width': 400}),
    html.Div([
            dcc.Loading(
            id="loading-2",
            children=[html.Div([dcc.Graph(id='figure-2')])],
            type="circle"),
            html.Button(id="input-2", children='Input triggers nested spinner')
        ], style={'width': 400})
    ])
@app.callback(Output('page-body', 'children'),
              [Input('url', 'value')])
def page(pathname):
    return make_layout(pathname)
@app.callback(Output("figure-container", "children"), [Input("input-1", "n_clicks")])
def input_triggers_nested(n_clicks):
    time.sleep(2)
    fig = go.Scatter(
        x=np.random.random(size=10),
        y=np.random.random(size=10)
    )
    return dcc.Graph(figure=dict(data=[fig]), id='figure-1')
@app.callback(Output("figure-2", "figure"), [Input("input-2", "n_clicks")])
def input_triggers_nested(n_clicks):
    time.sleep(2)
    fig = go.Scatter(
        x=np.random.random(size=10),
        y=np.random.random(size=10)
    )
    return dict(data=[fig])
if __name__ == "__main__":
    app.run_server(debug=True, port=8053)
Because the Loading components are being appended to page-body via the make_layout function, the spinners aren't showing upon initial loading. I suspect this is because we're not setting the loading_state property correctly on nested components, or, the requestQueue does not handle nested component updates properly.
I have the same problem on a multipage app. Any news on this?
I've also just discovered this problem on my multipage app, so would be interested in any updates as well.
I as well am having similar erratic loading animation behavior with my multipage app, so just like the people above me, I would be interested in an update regarding this issue.
I had the same problem following the tutorial but I found two workarounds to solve it.
One is using dcc.Interval to refresh the page after loading it, and limiting the number of updates by max_intervals. However, this method is inefficient since it will unnecessarily refresh the page several times.
The better solution I found is to combine dash apps with WSGI Apps. I modified the tutorial and tested the method on my app, witch is formed by an image gallery (index page) and zoom-in images (zoom-in pages). The method works well and is faster than the previous workaround. Here is a simplified test code, you can have a try:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from flask import Flask, redirect
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware
# Host wsgi app
flask_app = Flask(__name__)
@flask_app.route('/')
def index():
    # redirect to image gallery dash app
    return redirect('/index')
# Image gallery dash app
app_index = dash.Dash(
    'app_index',
    requests_pathname_prefix='/index/'
)
app_index.layout = html.Div([
    html.H1('Image gallery'),
    html.Div([
        html.A(
            html.Img(src='http://www.kanahei.com/upload/2019/12/12_wpsam.jpg'),
            href='/zoomin/image1'),
        html.A(
            html.Img(src='http://www.kanahei.com/upload/2019/11/11_wpsam.jpg'),
            href='/zoomin/image2'),
    ])
])
# Zoomin images dash app
app_zoomin = dash.Dash(
    'app_zoomin',
    requests_pathname_prefix='/zoomin/'
)
app_zoomin.layout = html.Div([
    dcc.Location(id='url'),
    html.H1('Zoomin image'),
    html.Div([
        html.Div(id='pathname'),
        html.Img(id='zoomin_image',
                 style={'max-width': '600px',
                        'max-height': '600px'}),
    ]),
    html.Div([
        html.A('Go back to gallery', href='/'),
    ])
])
@app_zoomin.callback(
    [Output('zoomin_image', 'src'),
     Output('pathname', 'children')],
    [Input('url', 'pathname')])
def update_zoomin_images(pathname):
    if pathname == '/zoomin/image1':
        return 'http://www.kanahei.com/upload/2019/12/01_16x9.jpg', pathname
    elif pathname == '/zoomin/image2':
        return 'http://www.kanahei.com/upload/2019/11/01_16x9.jpg', pathname
    return None, pathname
# Combine apps
application = DispatcherMiddleware(flask_app, {
    '/index': app_index.server,
    '/zoomin': app_zoomin.server,
})
# Run server
if __name__ == '__main__':
    run_simple('0.0.0.0', 8050, application)
I can confirm this issue. Is there any plan in place to get this resolved?
Have the same issue, is there any update on this? Thx!
I have the same issue as well
Same here. Any update?
Was there any solution to this problem? Cheers.
Just keeping this alive, I'm having the same problem.
I'm running into this too. I confirmed with vanilla dash, but first encountered this when using the excellent dash-mantine-components. The library demos a button that shows a loading spinner & greys itself out while being clicked (link), but it unfortunately does not work if the button is defined in a function.
Defining components within functions is absolutely essential for anything more than the simplest of apps. The code gets too out of hand with everything defined at the module level; it's disappointing that this doesn't work. I don't know where to begin debugging this or if help is even wanted, but I'd be willing to try digging in myself with a little guidance.
Having the same issue. Is there any workaround for this?
I know this is an old issue, but there seems to be recent activity. I ran the original example and everything looks fine to me. Can anyone provide a recent example that replicates this issue? Just asking because I'm working on a dcc.Loading PR right now.
closed by #2760