diff --git a/components/dash-core-components/src/fragments/Dropdown.react.js b/components/dash-core-components/src/fragments/Dropdown.react.js index 0464fb8ff4..6847be025d 100644 --- a/components/dash-core-components/src/fragments/Dropdown.react.js +++ b/components/dash-core-components/src/fragments/Dropdown.react.js @@ -39,10 +39,10 @@ const Dropdown = props => { const { id, clearable, - searchable, multi, options, setProps, + search_value, style, loading_state, value, @@ -122,7 +122,7 @@ const Dropdown = props => { useEffect(() => { if ( - !searchable && + !search_value && !isNil(sanitizedOptions) && optionsCheck !== sanitizedOptions && !isNil(value) diff --git a/components/dash-core-components/tests/integration/dropdown/test_remove_option.py b/components/dash-core-components/tests/integration/dropdown/test_remove_option.py index 6986380b45..a90ffe400c 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_remove_option.py +++ b/components/dash-core-components/tests/integration/dropdown/test_remove_option.py @@ -1,6 +1,8 @@ import json -from dash import Dash, html, dcc, Output, Input +import pytest + +from dash import Dash, html, dcc, Output, Input, State from dash.exceptions import PreventUpdate @@ -11,7 +13,8 @@ ] -def test_ddro001_remove_option_single(dash_dcc): +@pytest.mark.parametrize("searchable", (True, False)) +def test_ddro001_remove_option_single(dash_dcc, searchable): dropdown_options = sample_dropdown_options app = Dash(__name__) @@ -22,7 +25,7 @@ def test_ddro001_remove_option_single(dash_dcc): dcc.Dropdown( options=dropdown_options, value=value, - searchable=False, + searchable=searchable, id="dropdown", ), html.Button("Remove option", id="remove"), @@ -38,18 +41,17 @@ def on_click(n_clicks): @app.callback(Output("value-output", "children"), [Input("dropdown", "value")]) def on_change(val): - if not val: - raise PreventUpdate - return val or "None" + return val or "Nothing Here" dash_dcc.start_server(app) btn = dash_dcc.wait_for_element("#remove") btn.click() - dash_dcc.wait_for_text_to_equal("#value-output", "None") + dash_dcc.wait_for_text_to_equal("#value-output", "Nothing Here") -def test_ddro002_remove_option_multi(dash_dcc): +@pytest.mark.parametrize("searchable", (True, False)) +def test_ddro002_remove_option_multi(dash_dcc, searchable): dropdown_options = sample_dropdown_options app = Dash(__name__) @@ -62,7 +64,7 @@ def test_ddro002_remove_option_multi(dash_dcc): value=value, multi=True, id="dropdown", - searchable=False, + searchable=searchable, ), html.Button("Remove option", id="remove"), html.Div(id="value-output"), @@ -84,3 +86,64 @@ def on_change(val): btn.click() dash_dcc.wait_for_text_to_equal("#value-output", '["MTL"]') + + +def test_ddro003_remove_option_multiple_dropdowns(dash_dcc): + app = Dash(__name__) + app.layout = html.Div( + [ + dcc.Dropdown( + id="available-options", + multi=True, + options=sample_dropdown_options, + value=["MTL", "NYC", "SF"], + ), + dcc.Dropdown( + id="chosen", + multi=True, + options=sample_dropdown_options, + value=["NYC", "SF"], + ), + html.Button(id="remove-btn", children="Remove"), + html.Button(id="submit-btn", children="Submit"), + html.Div(id="value-output"), + html.Div(id="options-output"), + ], + ) + + @app.callback( + Output("chosen", "options"), + Input("available-options", "value"), + ) + def update_options(available_options): + if available_options is None: + return [] + else: + return [{"label": i, "value": i} for i in available_options] + + @app.callback( + Output("available-options", "options"), [Input("remove-btn", "n_clicks")] + ) + def on_click(n_clicks): + if not n_clicks: + raise PreventUpdate + return sample_dropdown_options[:-1] + + @app.callback( + [Output("value-output", "children"), Output("options-output", "children")], + Input("submit-btn", "n_clicks"), + State("chosen", "options"), + State("chosen", "value"), + ) + def print_value(n_clicks, options, value): + if not n_clicks: + raise PreventUpdate + return [json.dumps(value), json.dumps([i["value"] for i in options])] + + dash_dcc.start_server(app) + btn = dash_dcc.wait_for_element("#remove-btn") + btn.click() + btn = dash_dcc.wait_for_element("#submit-btn") + btn.click() + dash_dcc.wait_for_text_to_equal("#value-output", '["NYC"]') + dash_dcc.wait_for_text_to_equal("#options-output", '["MTL", "NYC"]')