Black Lives Matter. Please consider donating to Black Girls Code today.

Stop loading the layout in the middle of dcc.loading and load a new layout

Hi,

I added a loader using dcc.Loading into my output. My navbar is on my initial page and I’m loading layouts of a multi-page app. But when I load different layouts the Loader disables my Navbar and If I click an element on the navbar while loading, it loads that page after the current page is loaded. I want to have full control over my navbar and wantt the loader to load a different link in the navbar even when it is spinning. How can I do that Thank You.

You just need to have the children of your dcc.Loader not contain your Navbar.

2 Likes

It doesn’t contain my navbar. Can you show me a tried example that works? Thanks.

I took this example from Dash’s online tutorials, adding the sleep function to aid in visualization and wrapping dcc.Loading around the page-content div.

import dash
import dash_core_components as dcc
import dash_html_components as html
from time import sleep

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        # represents the URL bar, doesn't render anything
        dcc.Location(id='url', refresh=False),

        # This code could be your navbar - unaffected by dcc.Loading
        dcc.Link('Navigate to "/"', href='/'),
        html.Br(),
        dcc.Link('Navigate to "/page-2"', href='/page-2'),

        # content will be rendered in this element
        dcc.Loading(
            html.Div(id='page-content')
        )
    ]
)


@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    sleep(3)
    return html.Div([
        html.H3('You are on page {}'.format(pathname))
    ])


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

Hi,

I ran through the above code. So, when the alternate link is clicked the current page doesn’t stop it’s processing. Nor, it processes them one after the other. It processes them concurrently.(For this reason my navbar doesn’t show the new page when clicked because page is still executing my first script). I want the current page to stop it’s processing since my dashboard is CPU intensive and Load the new page in the middle of processing when clicked in the Navbar.

#here are the code changes I made to verify this in the terminal

import dash
import dash_core_components as dcc
import dash_html_components as html
from time import sleep

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        # represents the URL bar, doesn't render anything
        dcc.Location(id='url', refresh=False),

        # This code could be your navbar - unaffected by dcc.Loading
        dcc.Link('Navigate to "/"', href='/'),
        html.Br(),
        dcc.Link('Navigate to "/page-2"', href='/page-2'),

        # content will be rendered in this element
        dcc.Loading(
            html.Div(id='page-content',children=['This is default.'])
        )
    ]
)


@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    sleep(1)
    for i in range(500):
        #here if other link is clicked, while the first 
        #loop is still executing, The next page is not loaded before it's completed

         #also, both loops are processed concurrently
        print(i)
    print("complete")
    return html.Div([
        html.H3('You are on page {}'.format(pathname))
    ])


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

Summary:

  • If, the current page that is returned using callback takes time to load, the dcc.loading(pre-loader) does’t stop processing the current page when a new link is clicked.

Need a way to stop the current layout to be processed and instead, load the new layout that is clicked in the middle of loading the first.