🚀 Gen 5 of the leading AI app deployment platform launches October 6. Click for the livestream.

Radio button with dynamically assigned options doesn't visualize correctly

I want to dynamically change the options of dcc.RadioItems initiated by clicking a html.Button. Therefore I have a callback that reacts on the Button click and changes the radio options.

When I add the callback to my code and start the app I cannot select from the radio button’s initial options any more. To be precise, I can choose the option (i.e. the last clicked option is used) but the visual selection doesn’t change (so you think you are not changing the option). So the problem is that the visual representation of the radio button is broken somehow. After pressing the button, the options change as expected and all can be selected.

import dash
import dash_html_components as html
import dash_core_components as dcc

print(dash.__version__)  # I used 0.35.0 or 0.36.0rc1

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

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
    dcc.RadioItems(
        id='radio_items',
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': 'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),
    html.Button('Submit', id='button'),

])


@app.callback(
    dash.dependencies.Output('radio_items', 'options'),
    [dash.dependencies.Input('button', 'n_clicks')],
    [dash.dependencies.State('radio_items', 'value')])
def update_output(n_clicks, value):
    print('The input value was "{}" and the button has been clicked {} times'.format(
            value,
            n_clicks
        )
    )
    if n_clicks:
        new_options = [
                      {'label': 'New York City', 'value': 'NYC'},
                      {'label': 'Montréal', 'value': 'MTL'},
                      {'label': 'San Francisco', 'value': 'SF'},
                      {'label': 'Texas', 'value': 'TX'},
                  ]
        return new_options


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

I think the problem is related to the following: when the page loads all of the callbacks are fired once with the default values. In particular your update_output function gets called when n_clicks is None, and returns None to the options of radio_items. I think I managed to fix it by just specifying a default return value in update_output.

def update_output(n_clicks, value):
    print(
        'The input value was "{}" and the button has been clicked {} times'.format(
            value, n_clicks
        )
    )
    if n_clicks:
        new_options = [
            {"label": "New York City", "value": "NYC"},
            {"label": "Montréal", "value": "MTL"},
            {"label": "San Francisco", "value": "SF"},
            {"label": "Texas", "value": "TX"},
        ]
        return new_options
    return [
        {"label": "New York City", "value": "NYC"},
        {"label": "Montréal", "value": "MTL"},
        {"label": "San Francisco", "value": "SF"},
    ]

That seemed to work for me.