diff --git a/src/components/Dropdown.react.js b/src/components/Dropdown.react.js index 82b8a1f3d..271941aad 100644 --- a/src/components/Dropdown.react.js +++ b/src/components/Dropdown.react.js @@ -100,6 +100,7 @@ export default class Dropdown extends Component { setProps({value}); } }} + onInputChange={search_value => setProps({search_value})} {...omit(['setProps', 'value'], this.props)} /> @@ -195,6 +196,11 @@ Dropdown.propTypes = { */ searchable: PropTypes.bool, + /** + * The value typed in the DropDown for searching. + */ + search_value: PropTypes.string, + /** * Dash-assigned callback that gets fired when the input changes */ diff --git a/tests/integration/dropdown/test_dynamic_options.py b/tests/integration/dropdown/test_dynamic_options.py new file mode 100644 index 000000000..c3d75917b --- /dev/null +++ b/tests/integration/dropdown/test_dynamic_options.py @@ -0,0 +1,54 @@ +import dash +from dash.dependencies import Input, Output, State +from dash.exceptions import PreventUpdate +import dash.testing.wait as wait +import dash_core_components as dcc + + +def test_dddo001_dynamic_options(dash_duo): + options = [ + {"label": "New York City", "value": "NYC"}, + {"label": "Montreal", "value": "MTL"}, + {"label": "San Francisco", "value": "SF"}, + ] + + app = dash.Dash(__name__) + app.layout = dcc.Dropdown(id="my-dynamic-dropdown", options=[]) + + @app.callback( + dash.dependencies.Output("my-dynamic-dropdown", "options"), + [dash.dependencies.Input("my-dynamic-dropdown", "search_value")], + ) + def update_options(search_value): + if not search_value: + raise PreventUpdate + return [o for o in options if search_value in o["label"]] + + dash_duo.start_server(app) + + # Get the inner input used for search value. + dropdown = dash_duo.find_element("#my-dynamic-dropdown") + input_ = dropdown.find_element_by_css_selector("input") + + # Focus on the input to open the options menu + input_.send_keys("x") + + # No options to be found with `x` in them, should show the empty message. + dash_duo.wait_for_text_to_equal(".Select-noresults", "No results found") + + input_.clear() + input_.send_keys("o") + + options = dropdown.find_elements_by_css_selector(".VirtualizedSelectOption") + + # Should show all options. + assert len(options) == 3 + + # Searching for `on` + input_.send_keys("n") + + options = dropdown.find_elements_by_css_selector(".VirtualizedSelectOption") + + assert len(options) == 1 + print(options) + assert options[0].text == "Montreal" diff --git a/tests/integration/dropdown/test_search_value.py b/tests/integration/dropdown/test_search_value.py new file mode 100644 index 000000000..16941350c --- /dev/null +++ b/tests/integration/dropdown/test_search_value.py @@ -0,0 +1,28 @@ +import dash +from dash.dependencies import Input, Output, State +import dash.testing.wait as wait +import dash_core_components as dcc +import dash_html_components as html + + +def test_ddsv001_search_value(dash_duo): + app = dash.Dash(__name__) + app.layout = html.Div( + [dcc.Dropdown(id="dropdown", search_value="something"), html.Div(id="output")] + ) + + @app.callback( + Output("output", "children"), inputs=[Input("dropdown", "search_value")] + ) + def update_output(search_value): + return 'search_value="{}"'.format(search_value) + + dash_duo.start_server(app) + + # Get the inner input used for search value. + input_ = dash_duo.find_element("#dropdown input") + + dash_duo.wait_for_text_to_equal("#output", 'search_value="something"') + + input_.send_keys("x") + dash_duo.wait_for_text_to_equal("#output", 'search_value="x"') diff --git a/tests/unit/Dropdown.test.js b/tests/unit/Dropdown.test.js index 2cd3176e2..559add644 100644 --- a/tests/unit/Dropdown.test.js +++ b/tests/unit/Dropdown.test.js @@ -25,6 +25,7 @@ describe('Props can be set properly', () => { multi: false, placeholder: 'pick something', searchable: true, + search_value: "hello", style: {backgroundColor: 'hotpink'}, loading_state: { is_loading: false,