Callbacks not firing on page load

I have an app with some nested dropdowns, and I would like all of the the dropdown options to be loaded on page load, based on default values of the respective parent.

Since they are nested, the callbacks need to fire successively on page load, but this doesn’t seem to be the case.

While the upmost parent’s default value is shown on page load, the options in the following dropdowns don’t show up until I manually click on the first parent and select the default value.

Is the successive firing not the default behavior? What is the required structure to achieve what I want? I couldn’t find any examples in the docs that seem to cover this scenario.

Do you have a simple code example? There’s almost certainly a way to do what you want but it’s hard to interpret exactly what you mean.

Although for anything to do with page load I would personally suggest the better approach is to put this logic in to a layout function that can dynamically load the required information, e.g.:

import datetime

import dash
import dash_html_components as html


def get_layout():
    return html.Div(datetime.datetime.now().isoformat())


app = dash.Dash(__name__)
app.layout = get_layout


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

If you load this and refresh the page you can see the get_layout function gets run each time, this gives you the ability to do dynamic things. This 1) Let’s you define all initial state correctly in a single function, and 2) Has much better front-end performance because everything comes through on page load and doesn’t need to wait for callbacks.

Thanks @Damian, I already had my initial layout in a function, so this was an easy fix based on your comment.

However, now I have the opposite problem:

The initial values all load with the initial layout, but then dash executes all the callbacks, which of course return the same default values as defined in the layout function. Since the app is somewhat resource intensive, I’d like to avoid this double-loading.

Is there any way to prevent dash from firing callbacks on page load?

Yes, in a future version of Dash callbacks won’t fire on page callback anyway, in the mean time you have to raise dash.exceptions.PreventUpdate in your callback.

Here I give 2 examples of it working, for the second one make sure you are on the newest version of Dash:

import datetime
import dash
import dash_html_components as html

def get_layout():
    return html.Div([
        html.Div(datetime.datetime.now().isoformat(), id='dont-update-me'),
        html.Div(id='input-trigger')
    ])

app = dash.Dash(__name__)
app.layout = get_layout

@app.callback(output=dash.dependencies.Output('dont-update-me', 'children'),
              inputs=[dash.dependencies.Input('input-trigger', 'n_clicks')])
def dont_fire(n_clicks):
    # Classical Approach
    if n_clicks is None:
        raise dash.exceptions.PreventUpdate

    # Fancier approach that you can copy and paste in any callback
    if all(t['value'] is None for t in dash.callback_context.triggered):
        raise dash.exceptions.PreventUpdate

    return 'Noooo, I got updated'

if __name__ == '__main__':
    app.run_server()
1 Like

That sounds great!

The first option is unfortunately not going to work for me because dcc.Dropdown doesn’t have any equivalent to n_clicks (correct me if I’m missing something here).

The second option doesn’t seem to work for me either. I’m on dash 0.43.

My callback (minimal version) looks like this:

layout = html.Div([dcc.Dropdown(
                id='selector',
                options=[{'label':'Defaultlabel', 'value':'default'}],
                value='default',
                placeholder="Select an option"
            ),
            html.Div(id='outputdiv')
            )]

@app.callback(
    Output('outputdiv', 'children'),
    [Input('selector', 'value')])
def update_filter(surveyID):
    if all(t['value'] is None for t in dash.callback_context.triggered):
        print('update_filter exception raised')
        raise PreventUpdate
    else:
        return 'update_filter exception failed'

But the console always throws update_filter exception failed (or similar for other callbacks) on page load, indicating that the exception was not raised.

I’m not sure what additional information I could provide to help find the issue. The callbacks use prepopulated dropdowns as inputs.

For what it’s worth, I believe the reason it didn’t work might be that my app is behind a login page, meaning that the main page itself is already the output of a Callback that forwards the user to the main page after logging in. Although technically I believe that it should still not cause the callbacks to fire twice.

I managed to come up with a workaround anyways by placing my drop-down inside of a button without any styling, and using that button in the manner proposed by you initially. The button basically only serves to check if someone has clicked on the drop-down.

Unfortunately this is not ideal for accessibility, since someone without a mouse will not click on this invisible button and therefore the Callback will never get triggered. I look forward to the time when callbacks are not fired by default on first load.

Hello Damian,
I was wondering if you had any simple examples that utilizes this method but for multi page apps?

I split up my application into 3 pages or ‘apps’, the second contains a data-table and the third page contains graphs that take in the data from the table and plot them in a simple bar graph. The issue I am facing is that the graphs do not load when i get to the third page.

I emulated the method in the documentation but to no avail. I cannot seem to find any other examples.

I would appreciate your help,

thank you!