plotly / dash-core-components

OBSOLETE: now part of https://github.com/plotly/dash
https://dash.plotly.com
MIT License
270 stars 146 forks source link

‼️ Dropdown custom search not working #935

Open ViacheslavLabs opened 3 years ago

ViacheslavLabs commented 3 years ago

Explanation

Search is very convenient for dropdowns. Usually, a user may search by a nickname or with mistakes. Example:

The solution in dash docs is to provide options with callback on search_value input.

BUG: the solution doesn't work because dcc Dropdown will always try to search over options by itself. BUG Solution: provide the option to turn off the front-end search.

Quick example

import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

app.layout = html.Div([
    'Location',
    dcc.Dropdown(id="multi-dropdown", multi=True)
])

@app.callback(
    Output("multi-dropdown", "options"),
    Input("multi-dropdown", "search_value"),
)
def update_multi_options(search_value):

    options = [
        {'label': 'Always find that option 1',
         'value': '1'},
        {'label': 'Always find that option 2',
         'value': '2'},
    ]
    return options

if __name__ == "__main__":
    app.run_server(debug=True, port=8051)

Current behavior for example: Screenshot 2021-03-16 at 20 24 47 Expected behavior for example: Always show provided options from the callback on an user search.

maratori commented 3 years ago

I've faced with the same issue while trying to implement fuzzy find like in Sublime Text. Does anyone know a workaround?

maratori commented 3 years ago

Moreover (besides that filter is applied on the frontend side) it also sorts options by the value if search_value is not empty.

https://user-images.githubusercontent.com/16486128/115563727-83960680-a2c0-11eb-8d69-9ba44e45151f.mov

import json
import dash
import dash.dependencies as dep
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash(__name__)
app.layout = html.Div([
    dcc.Dropdown(id="dropdown"),
    html.Pre(id="output", style=dict(marginTop="150px")),
])

@app.callback(dep.Output("output", "children"),
              dep.Output("dropdown", "options"),
              dep.Input("dropdown", "search_value"))
def filter_dropdown(search_value: str):
    options = [
        {"label": "#1 - value=1 - xxx", "value": 1},
        {"label": "#2 - value=3 - xxx", "value": 3},
        {"label": "#3 - value=4 - xxx", "value": 4},
        {"label": "#4 - value=2 - xxx", "value": 2},
    ]
    return [
        f"search_value = {search_value!r}\n"
        f"options = {json.dumps(options, indent=4)}",
        options
    ]

app.run_server()