from dash import Dash, dcc, html, Input, Output, State, callback, no_update
app = Dash(__name__)
city_selections = [
"New York City",
"Montreal",
"San Francisco",
"Denver",
"Jackson Hole",
"Seattle",
]
app.layout = html.Div(
[
dcc.Dropdown(
id="dropdown",
options=["Montreal", "San Francisco"],
value=["Montreal", "San Francisco"],
multi=True,
)
]
)
@callback(
Output("dropdown", "options"),
Input("dropdown", "search_value"),
State("dropdown", "value"),
)
def options_one(user_input, selections):
"""
Callback fires every time the 'search_value' changes
in the dropdown menu, which is whenever the user adds
or deletes a character from the search field.
"""
# nothing currently selected in the searchbar
if not selections:
selections = []
# user has deleted any typed search term
if not user_input:
return no_update
# patter match strings in selectable options against the user's input
opts = [city for city in city_selections if user_input.lower() in city.lower()]
print(f"User input: {user_input}")
print(f"Possible options: {opts}")
"""
Normally, the length of the 'city_selections' value in our app's context
is around 15,000 entries long, which is too long for the searchbar,
so we return a trimmed options list like this, limiting the number of options
to a manageable 250 + selections values:
if(len(opts) > 250):
return opts[:250] + selections
else:
return opts + selections
"""
# concat previous selections onto options, otherwise they won't
# be kept as selected values.
return opts + selections
if __name__ == "__main__":
app.run_server(debug=True)
This MRE implements the way we handle option filtering in our app.
What would be nice is if the parameter ‘debounce’ was available like @jinnyzor mentioned
so that the callback would only fire when the user stopped typing for a reasonable amount of time.