Update dcc.Dropdown default values on button click dynamically

Hello, I have a button and a dcc Dropdown. As you can see from my example I want to Update the options in the Dcc.Dropdown dynamically. That works. I would also like to display the newly created options directly in the dropdown, instead of having to insert them by hand. Is there a possibility to achieve this? or any workaround?

import dash
from dash import Input, Output, State, ClientsideFunction, html, dcc, ctx
from dash.exceptions import PreventUpdate
import json



app = dash.Dash(__name__)


Button = html.Button('Submit', id='submit', n_clicks=0)

ClickStore = dcc.Store(id="ClickStore", storage_type="session")



Dropdown = dcc.Dropdown(
    options=[],
    multi=True,
    id="dropdown")

app.layout = html.Div([
    ClickStore,
    Button,
    Dropdown
])


#Update Store
@app.callback(Output("ClickStore", "data"),
              Input("submit","n_clicks"),
              State('ClickStore', 'data'),

               prevent_initial_call=True)

def update_Store(nclicks, json_DictStore):
    if nclicks==0:
        raise PreventUpdate

    if nclicks == 1:
        DictStore=[]
        optiondict = {"label": nclicks, "value": nclicks}
        DictStore.append(optiondict)
    if nclicks > 1:
        DictStore = json.loads(json_DictStore)
        optiondict = {"label": nclicks, "value": nclicks}
        DictStore.append(optiondict)
    

    json_DictStore = json.dumps(DictStore)
    return json_DictStore


#Update Dropdown
@app.callback(Output("dropdown", "options"),
              Input("ClickStore","modified_timestamp"),
              State("ClickStore","data"),
               )

def update_Dropdown(ts, json_DictStore):
    if ts is None or json_DictStore is None: 
     raise PreventUpdate

    DictStore = json.loads(json_DictStore)
    return DictStore





if __name__ == '__main__':
    app.run(host='127.0.0.1', port='3000', debug=True)

Hi @cosco !

How about that? :

Code
from dash import Input, Output, State, html, dcc, callback, Dash
import json

app = Dash(__name__)

app.layout = html.Div(
    [
        html.Button(id='btn-click', children='Submit'),
        dcc.Dropdown(id="dd-click", multi=True),
        dcc.Store(id="str-click", storage_type="session", data='[]')
    ]
)


# Update Store
@callback(
    Output("str-click", "data"),
    Input("btn-click", "n_clicks"),
    State('str-click', 'data'),
    prevent_initial_call=True
)
def update_store(n_clicks, json_store):
    dict_store = json.loads(json_store)
    dict_store.append(f'Label_{n_clicks}')
    return json.dumps(dict_store)


# Update Dropdown
@callback(
    Output("dd-click", "options"),
    Input("str-click", "data"),
)
def update_dropdown(json_store):
    return json.loads(json_store)


if __name__ == '__main__':
    app.run(port=3000, debug=True)

I refactored a lot to achieve want you requested, but that may be too much, that depends on what you want to do next with that…

Actually we can go further in the refactoring, it’s possible to merge the two callback to update the store and the dropdown at the same time, or even drop the store if you don’t need it elsewhere… :grin:

Animation

Hello Skiks, okay fine I want it to display in the dropdown without inserting it by hand though.

You mean you want to have the new options directly selected in the dropdown?
Like:

Code
from dash import Input, Output, State, html, dcc, callback, Dash
import json

app = Dash(__name__)

app.layout = html.Div(
    [
        html.Button(id='btn-click', children='Submit'),
        dcc.Dropdown(id="dd-click", multi=True),
        dcc.Store(id="str-click", storage_type="session", data='[]')
    ]
)


# Update Store
@callback(
    Output("str-click", "data"),
    Input("btn-click", "n_clicks"),
    State('str-click', 'data'),
    prevent_initial_call=True
)
def update_store(n_clicks, json_store):
    list_store = json.loads(json_store)
    list_store.append(f'Label_{n_clicks}')
    return json.dumps(list_store)


# Update Dropdown
@callback(
    Output("dd-click", "options"),
    Output("dd-click", "value"),
    Input("str-click", "data"),
)
def update_dropdown(json_store):
    list_store = json.loads(json_store)
    return list_store, list_store

if __name__ == '__main__':
    app.run(port=3000, debug=True)

Animation

1 Like

Haha yes Skiks, thank you!

1 Like