Build dynamic list of option for dropdown with input

I’m new to Dash and would like to understand how to build a dynamic list of options to the dropdown input, the list of options builds on as more input are entered. From the documentation, I think intermediate values are recommended. But it results in a callback output depends on the same input, for example, outputlist = inputlist.append(‘C’). When I tried the following:

@app.callback(Output('new-watchlist', 'children'),
              [Input('add-button', 'n_clicks'),
               Input('new-watchlist', 'children')],
              [State('ticker-input', 'value')]
              )
def stock_pick(n_clicks, ticker,watchList):
    
    if ticker is not None:
        watchList.append(ticker)
    print(watchList)
    return watchList

I got error loading the page. Same error happens even if I setup multiple intermediate values. Help is appreciated! Thanks in advance.

Capture

I was able to make some more progress as I looked more into the document about sharing data between callbacks.
https://dash.plot.ly/sharing-data-between-callbacks

I’m initiating the list and use the state of this list to update the list when “add” button is clicked.

# Add Ticker to New watchlist when add button is clicked


@app.callback(Output('new-watchlist', 'children'),
              [Input('add-button', 'n_clicks')],
              [State('ticker-input', 'value'),
               State('new-watchlist', 'children')]
              )
def stock_pick(n_clicks, ticker, watchList):
    # watchList = ['AMZN', 'GOOG', 'TSLA']
    # print(watchList)
    if(watchList is None):
        watchList = ['AMZN', 'GOOG', 'TSLA']
    else:
        if ticker is not None and ticker not in watchList:
            watchList.append(ticker)
        print("after add")
        print(watchList)
    return watchList

After “Add” button clicked, I got the new list
after add
[‘AMZN’, ‘GOOG’, ‘TSLA’, ‘C’]

Now that I have the list, I’m using the chained callback to update the options of my dropdown as the document suggests.

html.Div(id='new-watchlist'),

However, the very last piece is not working for me yet: this callback is not triggered when the value (new-watchlist children) is updated. One thing interesting is that this callback does get called once when the page is first loaded as the document specified, but not when the value are changed.

# Update Options in dropdown-watchlist


@app.callback(Output('dropdown-watchlist', 'options'),
              [Input('new-watchlist', 'children')]
              )
def update_dropdown(watchList):
    print("in update_dropdown")
    print(watchList)
    return [{'label': i, 'value': i} for i in watchList]

Advise is appreciated.

One more update.
I discovered from the document that Data has to be converted to a string like JSON for storage and transport.

So I converted

# Add Ticker to New watchlist when add button is clicked


@app.callback(Output('new-watchlist', 'children'),
              [Input('add-button', 'n_clicks')],
              [State('ticker-input', 'value'),
               State('new-watchlist', 'children')]
              )
def stock_pick(n_clicks, ticker, jsonWatchList):
    print('json Watchlist is ')
    print(jsonWatchList)

    # watchList = ['AMZN', 'GOOG', 'TSLA']
    # print(watchList)
    if(jsonWatchList is None):
        watchList = ['AMZN', 'GOOG', 'TSLA']
    else:
        watchList = json.loads(jsonWatchList)
        print('watchList after json loads')
        print(watchList)
        if ticker is not None and ticker not in watchList:
            watchList.append(ticker)
        print("after add")
        print(watchList)
    outJson = json.dumps(watchList)
    print("outJson is")
    print(outJson)
    return outJson

Also changed the input to take the json data.

# Update Options in dropdown-watchlist


@app.callback(Output('dropdown-watchlist', 'options'),
              [Input('new-watchlist', 'children')]
              )
def update_dropdown(jsonWatchList):
    watchList = json.loads(jsonWatchList)
    print("in update_dropdown")
    print(watchList)
    return [{'label': i, 'value': i} for i in watchList]

I got the same behavior as before: callback function update_dropdown was only triggered once during page load, but not when the list is changed.

outJson is
[“AMZN”, “GOOG”, “TSLA”]
in update_dropdown
[‘AMZN’, ‘GOOG’, ‘TSLA’]