Autocomplete with Dropdown object when setting app.layout dynamically

Somewhat related to the post on multi-page dash app, but here’s the strange behavior I’m seeing. To set this up, the dropdown object has a neat feature that performs a dynamic search of dropdown values, displaying only the values that match the search text. This works great when app.layout is set explicitly:

app.layout = html.Div( [ dcc.Dropdown(…) ] ) (also see User guide for an example)

However, when I reconfigure app.layout to be set dynamically, I lose that autocomplete behavior. Try out the code below. I wonder whether there’s something about how dynamic layouts are implemented here (with a callback) that prevents the search from working. (I need the dynamic layout because I’m scraping parameters from the url to initialize state (using the new dcc.Location object), as was suggested the thread linked above).

# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State, Event

app = dash.Dash()

app.layout = html.Div([ dcc.Location(id='url', refresh=False),
                               html.Div(id='page-content') 
                                                        ])  

@app.callback(Output('page-content', 'children'),[Input('url', 'pathname')]) 
def generate_layout(url): 
    return html.Div([
html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montré', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
value=['MTL', 'SF'],
multi=True
),
], style={'columnCount': 2})

if __name__ == '__main__':
    app.run_server(debug=True, host='0.0.0.0')
1 Like

I’ve modified your example slightly and this seems to work for me ok:

# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State, Event

app = dash.Dash()

app.config.supress_callback_exceptions=True

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content')])

@app.callback(Output('page-content', 'children'),[Input('url', 'pathname')])
def generate_layout(url):
    return html.Div([
        html.Label('Multi-Select Dropdown'),
        dcc.Dropdown(
            options=[
                {'label': 'New York City', 'value': 'NYC'},
                {'label': u'Montréal', 'value': 'MTL'},
                {'label': 'San Francisco', 'value': 'SF'}
            ],
            value=['MTL', 'SF'],
            multi=True,
            id='input'
        ),
        html.Div(id='output')
    ])


@app.callback(Output('output', 'children'), [Input('input', 'value')])
def display_output(value):
    return 'You have selected "{}"'.format(value)

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

From your example, it looks like you aren’t supplying a callback to the dropdown that you are rendering. In this case, the dropdown autocomplete doesn’t work. Are you using the dropdown without a callback on its value in practice?

Hi Chris,
Thanks for the fix! Yes, you’re correct, I wasn’t using callbacks on outputs because I was directly querying the dropdown ‘value’ for downstream functionality and so I figured I didn’t need the ‘output’ object. I must be confused about the design principal that requires the callback in this scenario. Could you say a few words about that?

Thanks again!

What do you mean by this? In other words, how are “querying” this value if not through a callback?

Dash user interface components like Dropdown and Input are designed to work with callbacks - as the user modifies the value, the app “responds” by calling a callback. These components aren’t useful to the user without these types of callbacks: without a callback or without some external JS hook, changing the dropdown’s item won’t affect the app in any other way, so why include it?

I think this could be considered a bug - the dropdowns should function the same way with or without callbacks assigned to them. However, using the dropdown without a callback assigned to it is uncommon, and so this behaviour is sort of neglected.

oh my bad. I was using a callback in my original webpage and that webpage is working now. For some reason I thought you were saying the specific ‘output’ div object in the example above was required to catch the value selection. I realize now that is not what you meant.

I did update dash from quite an older version since the time I posted this message, so that probably explains why my page is working now.

sorry for the confusing posts :slight_smile:

1 Like