Allow User to Create New Options in `dcc.Dropdown`

I was wondering if there is a way, to allow users to create new options while selecting from a (potentially empty) dcc.Dropdown.

The main idea is for this to also function as a data entry tool. The great autocomplete / search functionality available in dcc.Dropdown would make it easy for users to keep track of what they entered.

To be clear, this idea is basically Shiny’s selectizeInput function with the option of create=TRUE:
https://shiny.rstudio.com/articles/selectize.html

selectizeInput(

‘foo’, label = NULL, choices = state.name,
options = list(create = TRUE)
)

The user starts entering data, and gets suggestions.
They can select one of the suggestions, or hit Enter to create a new value.

Thanks!

Yep! You can create a callback that targets the options property of the dropdown component. The trick is also including the options as a State of the callback so we can append the new value to the current values (you can’t add it as an Input as this will result in a cyclic dependency)

@app.callback(Output('dropdown', 'options'), [Input('input', 'value')], [State('dropdown', 'options')])
def callback(new_value, current_options):
    if not new_value:
        return current_options

    current_options.append({'label': new_value, 'value': new_value})
    return current_options

This is not quite as streamlined as the Shiny behaviour you described though, as this is not built into the dropwdown component, just using Dash itself to update the options. So you’ll need to have an Input component (here with ID ‘input’) for users to put their new value in. Also it just occurs to me know, that you probably don’t want that being triggered by an Input dependency, as you’ll get a new option for every character someone types. Maybe a click event on a button could be safer:

app.layout = html.Div([
    dcc.Dropdown(
        id='dropdown',
        options=[
            {'label': 'a', 'value': 'a'},
            {'label': 'b', 'value': 'b'},
            {'label': 'c', 'value': 'c'},
        ],
        value='a'
    ),
    dcc.Input(id='input', value=''),
    html.Button('Add Option', id='submit'),
])

@app.callback(
    Output('dropdown', 'options'),
    [],
    [State('input', 'value'), State('dropdown', 'options')],
    [Event('submit', 'click')]
)
def callback(new_value, current_options):
    if not new_value:
        return current_options

    current_options.append({'label': new_value, 'value': new_value})
    return current_options
2 Likes

Thanks for the immediate response!

Just ran the code and it seems to work. I can simply print out the entered values, so the user can keep track of what was entered.

You’re right about cyclic dependency. I tried to modify this recipe, https://github.com/plotly/dash-recipes/blob/master/dash-append-element-dropdown-options.py and every letter I typed ended up in the list of options.

I wasn’t very familiar with Event either.

Thanks again!

1 Like

Would you happen to have any recommendations for an updated solution, now that the Event module has been removed?

Change Event to Input and it will work the same.

@app.callback(
    Output('dropdown', 'options'),
    [Input('submit', 'click')]
    [State('input', 'value'),
     State('dropdown', 'options')],
)
def callback(n_clicks,new_value,current_options):
    if not n_clicks:
        return no_update
    ...