Dropdown not populating with return None

Hello,
After a non trivial amount of troubleshooting I came to realize that a call back to populate options which, on first render, either does not execute a return statement (because the return is in an if statement that doesn’t fire initially) or returns None will disable the abilty for that callback to populate options in subsequent call backs.
An example:

this will never populate options

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id='my-id', placeholder='enter text sperated by comma', type='text'),
    dbc.Button('show charts',id='button',color='primary', disabled=False),
    dcc.Dropdown(id='dd')
])


@app.callback(Output('dd','options'),
               [Input('button', 'n_clicks')],
               [State('my-id', 'value')])
def update_selectStep_list(clicks,prodSteps):
    if prodSteps is not None:
        vals=[i.strip() for i in prodSteps.upper().split(',')]
        return [{'label': i, 'value': i} for i in vals]
    else:
        return None

if __name__ == "__main__":
    app.run_server(debug=False)

Nor will this

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id='my-id', placeholder='enter text sperated by comma', type='text'),
    dbc.Button('show charts',id='button',color='primary', disabled=False),
    dcc.Dropdown(id='dd')
])


@app.callback(Output('dd','options'),
               [Input('button', 'n_clicks')],
               [State('my-id', 'value')])
def update_selectStep_list(clicks,prodSteps):
    if prodSteps is not None:
        vals=[i.strip() for i in prodSteps.upper().split(',')]
        return [{'label': i, 'value': i} for i in vals]

if __name__ == "__main__":
    app.run_server(debug=False)

but this WILL

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id='my-id', placeholder='enter text sperated by comma', type='text'),
    dbc.Button('show charts',id='button',color='primary', disabled=False),
    dcc.Dropdown(id='dd')
])


@app.callback(Output('dd','options'),
               [Input('button', 'n_clicks')],
               [State('my-id', 'value')])
def update_selectStep_list(clicks,prodSteps):
    if prodSteps is not None:
        vals=[i.strip() for i in prodSteps.upper().split(',')]
        return [{'label': i, 'value': i} for i in vals]
    else:
        return {}

if __name__ == "__main__":
    app.run_server(debug=False)

This seems like odd behavior since in the 2nd example the return statement is not being fired at all.

Thanks for the insight.

I was able to get your first set of code to work by:

  • entering comman separated list
  • pressing return
  • clicking the “show charts” button

The second set of code (without else clause) appears to fail in rendering since all callbacks are fired on page load and your callback does not have a return case if prodSteps is None. Instead of returning None, I recommend returning no_update (include from dash.dash import no_update.

The third case works for the same reason the first case did…it has a return value for all paths.

I re ran the first case (with return None) and it doesn’t populate the list however, if I use ‘no_update’ it does populate. Thanks for that tip, I will use that.

Blockquote
The second set of code (without else clause) appears to fail in rendering since all callbacks are fired on page load and your callback does not have a return case if prodSteps is None .
Blockquote

I guess I was thinking that if nothing was returned it just wouldnt update the options but now that I think about it not having a return causes it to break somewhere else since it is expecting a return of something.

Im still learning python, is there somewhere it is stated that a return statement is explicitly required or is it part of the app.callback method?

Thanks for your help.

Barring any correction from a Dash expert, I believe all app.callbacks need to have vaild return values in order for successful execution/rendering. Outside of Dash, and stricktly speaking of python, return values are optional and will return None if no return value is specified.

1 Like