Validate user's selections using conditionals

I’ve got this callback function:

@app.callback(Output('user-selections', 'children'),
              [Input('submit-button', 'n_clicks')],
              [State('b1-sel', 'value'),
               State('b2-sel', 'value'),
               State('year-sel', 'value'),
               State('month-sel', 'value')])
def update_output(n_clicks, year, month, b1, b2):
    if n_clicks < 1:
        return "Click Submit after selections to begin."
    elif None in [year, month, b1, b2]:  # This works!
        return "Please complete all fields prior to submission."
    else:
        return u'''
        The Button has been pressed {} times,
        b 1 is "{}",
        b 2 is "{}",
        Year is "{}",
        Month is "{}"
        '''.format(n_clicks, year, month, b1, b2)

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

The above function works for when the user hasn’t made selections or hasn’t yet clicked “submit” but I was wondering why replacing the above elif with:

    elif ((None in [year, month, b1, b2]) or (b1 == b2)): # ignores when b1==b2
        return "Please complete all fields and select different b1 b2 vals."

doesn’t work?

I suspect folks are going to suggest I dynamically narrow the results of b2's selection based on b1 but I am hoping there’s an easier way.

Do you get an error or does it ignore the or logic?

Can you post a executable example with the layout?

No error, ignores logic.

It’s essentially the same example from here. I just added some conditionals to the function. I’ve pasted that example below for convenience.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    dcc.Input(id='input-1-state', type='text', value='Montréal'),
    dcc.Input(id='input-2-state', type='text', value='Canada'),
    html.Button(id='submit-button', n_clicks=0, children='Submit'),
    html.Div(id='output-state')
])


@app.callback(Output('output-state', 'children'),
              [Input('submit-button', 'n_clicks')],
              [State('input-1-state', 'value'),
               State('input-2-state', 'value')])
def update_output(n_clicks, input1, input2):
    return u'''
        The Button has been pressed {} times,
        Input 1 is "{}",
        and Input 2 is "{}"
    '''.format(n_clicks, input1, input2)


if __name__ == '__main__':
    app.run_server(debug=True)
@app.callback(Output('user-selections', 'children'),
          [Input('submit-button', 'n_clicks')],
          [State('b1-sel', 'value'),
           State('b2-sel', 'value'),
           State('year-sel', 'value'),
           State('month-sel', 'value')])
def update_output(n_clicks, year, month, b1, b2):

you have the value of b1-sel assigned to year, b2-sel assigned to month etc. The order of your function inputs in update_output should be in the order you listed them in the decorator.

Thank you! That worked. I didn’t even realize.

1 Like