How to keep the dropdown value after button click in Dash?

I have an application in which I want to update the dropdown values when the user inputs some text into the dropdown. So far, I managed to get the text from an Input text that the user inputs, but not from the dropdown. The dropdown keeps reseting after clicking in any part of the screen or on the button.

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


app = dash.Dash(
    external_stylesheets=[
        dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    [
        dcc.Input(id='helper'),
        dcc.Dropdown(id="my-dynamic-dropdown", options=[]),
        html.Br(),
        html.Br(),
        html.Br(),
        html.Br(),
        html.Br(),
        html.Br(),
        html.Br(),
        dbc.Button('Add to Dropdown', id='dropdown_button', n_clicks=0, color="info",
                   className="mr-1")
    ],

)

options = []


@app.callback(
    Output("my-dynamic-dropdown", "options"),
    Input('dropdown_button', 'n_clicks'),
    [State('my-dynamic-dropdown', 'options'),
    # State('helper', 'value')
    State('my-dynamic-dropdown', 'search_value')
     ]
)
def update_options(n_clicks,existing_options,helper_value):
    if helper_value is None:
        print("none value")
        return options
    else:
        print("helper value ",helper_value)
        options.append({'label': helper_value, 'value': helper_value})
        return options


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

Hi lola_bunny
The problem you have is that when the user clicks the button the ‘search_value’ of the dropdown goes to None.
perhaps you can store the ‘search_value’ in a dcc.Store ‘data’:

dcc.Store(id='store'),
@app.callback(
    Output("store", "data"),
    Input('my-dynamic-dropdown', 'search_value'),
    State("store", "data"),    
)

and then call it from the callback:

@app.callback(
    Output("my-dynamic-dropdown", "options"),
    Input('dropdown_button', 'n_clicks'),
    Input("store", "data"),
    State('my-dynamic-dropdown', 'options'),

and manage the callbacks to get the last value generated by the ‘search_value’ and add it to the options.
I hope it helps.

thanks so much!
here is the working code:

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

app = dash.Dash(
    external_stylesheets=[
        dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    [dcc.Store(id='store'),

     dcc.Input(id='helper'),
     dcc.Dropdown(id="my-dynamic-dropdown", options=[]),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     dbc.Button('Add to Dropdown', id='dropdown_button', n_clicks=0, color="info",
                className="mr-1")
     ],

)

options = []

elements = []


@app.callback(
    Output("store", "data"),
    Input('my-dynamic-dropdown', 'search_value'),
    State("store", "data"),
)
def get_search_value(search_value, data_store):
    if search_value is None or not search_value:
        print("EMPTY")
    else:
        data_store = search_value
        elements.append(data_store)
        return data_store


@app.callback(

    Output("my-dynamic-dropdown", "options"),
    Input('dropdown_button', 'n_clicks'),
    [
        State("store", "data"),
        State('my-dynamic-dropdown', 'options'),
        State('my-dynamic-dropdown', 'search_value')
    ]
)
def update_options(n_clicks, data_store, existing_options, helper_value):
    if not elements:
        print("EMPTY elements list")
        return options
    else:
        print("last element is ", elements[-1])
        print("data store value ", data_store)
        options.append({'label': elements[-1], 'value': elements[-1]})
        return options



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


But also, do you know how can I click anywhere in the page and keep the written input in the dropdown? I managed to add the new value to the dropdown, but whenever i click someplace in the page, the value becomes None

lola_bunny

First try looking into persistence and 'persistence_type' properties that allows to prevent the info to be clear with refresh.


I don’t know if it solve your issue. But could be usefull to prevent others.

I think you have to send the new option to the ‘value’ of the dropdown:

Output("my-dynamic-dropdown", "value"),

I see that the value of dropdown is only updated only after pushing the button… i mean that the input stays in the dropdown only after pushing button.

Sorry, I don’t understand your point.

Hi lola_bunny,

Here is the code with the ‘value’ output

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

app = dash.Dash(
    external_stylesheets=[
        dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    [dcc.Store(id='store'),

     dcc.Input(id='helper'),
     dcc.Dropdown(id="my-dynamic-dropdown", options=[]),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     html.Br(),
     dbc.Button('Add to Dropdown', id='dropdown_button', n_clicks=0, color="info",
                className="mr-1")
     ],

)

options = []

elements = []


@app.callback(
    Output("store", "data"),
    Input('my-dynamic-dropdown', 'search_value'),
    State("store", "data"),
)
def get_search_value(search_value, data_store):
    if search_value is None or not search_value:
        print("EMPTY")
    else:
        data_store = search_value
        elements.append(data_store)
        return data_store


@app.callback(

    Output("my-dynamic-dropdown", "options"),
    Output("my-dynamic-dropdown", "value"),
    Input('dropdown_button', 'n_clicks'),
    [
        State("store", "data"),
        State('my-dynamic-dropdown', 'options'),
        State('my-dynamic-dropdown', 'search_value')
    ]
)
def update_options(n_clicks, data_store, existing_options, helper_value):
    if not elements:
        print("EMPTY elements list")
        value= ({'label': "", 'value': ""})
        return options, "" 
    else:
        print("last element is ", elements[-1])
        print("data store value ", data_store)
        options.append({'label': elements[-1], 'value': elements[-1]})
        value= ({'label': elements[-1], 'value': elements[-1]})
        return options, elements[-1]



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

And it works as expected :upside_down_face:

1 Like

Thanks so much :slight_smile: :grin:

1 Like

But still, the ‘value’ of the dropdown is returned only after pushing the button. If the user clicks on any other part of the application other than the button, dropdown’s value resets

lola_bunny
Not in my code, I still have the value no matter what I do, also I add something in the input and the ‘value’ is still there in the dropdown. :thinking:

when you set the “value” of the dropdown it will be there until the users enters another value.

Yes, this happens when you set it. But before clicking the button, the value is not set, so the dropdown still resets when the user clicks in other parts of the page :slight_smile:

Well, thats why the button is there, if the user add a new element in the dropdown and then do not click the button saying ‘Add to Dropdown’ she/he will learn from that for the next time :laughing:

1 Like