Skip to content
This repository has been archived by the owner on Jun 3, 2024. It is now read-only.

Add search_value property to Dropdown #660

Merged
merged 11 commits into from
Sep 26, 2019
Merged

Add search_value property to Dropdown #660

merged 11 commits into from
Sep 26, 2019

Conversation

inytar
Copy link
Contributor

@inytar inytar commented Sep 26, 2019

This PR adds the search_value property to the Dropdown component. Using the search_value you can do server side filtering of the options as shown in the following example:

import dash
import dash_html_components as html
import dash_core_components as dcc

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

options=[
    {'label': 'New York City', 'value': 'NYC'},
    {'label': 'Montreal', 'value': 'MTL'},
    {'label': 'San Francisco', 'value': 'SF'}
]

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = dcc.Dropdown(id='my-dynamic-dropdown')


@app.callback(
    dash.dependencies.Output('my-dynamic-dropdown', 'options'),
    [dash.dependencies.Input('my-dynamic-dropdown', 'search_value')],
)
def update_options(search_value):
    return [o for o in options if search_value in o['label']]


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

This example will also be added to dash-cocs.

An example of a use-case of this feature is described in this forum topic.

Copy link
Collaborator

@alexcjohnson alexcjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @inytar - this looks great!

Can you exclude the build artifact changes from this PR? (You're about a day early before we do this automatically #659) That would be everything except src/ and tests/

And as far as tests go, I see the empty block in unit/Dropdown.test.js, I'm guessing that was just added when you needed to edit that file to get tests to pass, and you were planning to come back to it... but I think this would be better served by an integration test. Let's make a new folder tests/integration/dropdown and run a test against the same app you showed in the lead comment.

@inytar
Copy link
Contributor Author

inytar commented Sep 26, 2019

@alexcjohnson thanks for the review. I'll remove the artifacts.
About the test, I started writing it and then got stuck, I'm not really sure how I would test this. I'll look in the integration directory, see if I can find an example.

@alexcjohnson
Copy link
Collaborator

A good example is test_state_and_inputs in the Input tests - it shows how to start an app and send keypresses to the right component. Then you'll just have to figure out a selector that returns the option list and do something like:

wait.until(lambda: len(dash_duo.find_elements('<option selector>')) == <expected number>)
assert dash_duo.find_element('<option selector>').text == <expected option>

@inytar inytar requested a review from alexcjohnson September 26, 2019 14:02
)
def update_output(search_value):
call_count.value += 1
return 'search_value="{}"'.format(search_value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry, I missed this earlier - I think the test should use the same structure as the example app you gave, which is updating options from search_value in the same component. The reason this is important is (a) that's the primary use case for this prop, and (b) it will cause the dropdown to rerender, and we need to ensure that when it does the correct options are visible. I can certainly imagine errors in the component where on render it loses focus, or for some other reason it stops displaying the option list.

(BTW nota big deal but you can probably get rid of all the call_count stuff, that doesn't really matter for this test, we only care about what's going on within the browser)

@inytar
Copy link
Contributor Author

inytar commented Sep 26, 2019

@alexcjohnson I miss read your first comment and thought you just wanted a basic integration test. I've kept this test because I think it's good to keep a basic test that is easier to debug/understand if something fails. I've also added a test that updates the options dynamically from the server, I hope this is what you meant.

@inytar inytar requested a review from alexcjohnson September 26, 2019 18:39
import dash_core_components as dcc


def test_ddsv001_dynamic_options(dash_duo):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I was not clear about the suggestion. the TCID added in the previous test should be unique. more details refer to Notes #2 in example. https://dash.plot.ly/testing

this one should be sth like dddo001

Copy link
Collaborator

@alexcjohnson alexcjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bearing with our suggestions @inytar - very nicely done. Just the suggestion from @byronz about TCID uniqueness https://github.com/plotly/dash-core-components/pull/660/files#r328776554 and this will be ready to go! 💃

@alexcjohnson
Copy link
Collaborator

Oh, the linter had some complaints as well:

tests/integration/dropdown/test_dynamic_options.py:9:12: E225 missing whitespace around operator
tests/integration/dropdown/test_dynamic_options.py:36:5: E265 block comment should start with '# '

It looks like js linting also complained but that somehow doesn't cause the test run to fail... so don't worry about that, we'll get that separately.

@inytar
Copy link
Contributor Author

inytar commented Sep 26, 2019

Thanks for looking at this and the fast reviews! I enjoyed the process and hope I get to work with plotly dash more in the future.

@inytar
Copy link
Contributor Author

inytar commented Sep 26, 2019

Btw, this is the related example for the documentation. I'd be very happy if this can also be added.

@alexcjohnson alexcjohnson merged commit 57ef102 into plotly:dev Sep 26, 2019
@alexcjohnson
Copy link
Collaborator

oops I forgot to ask for a changelog entry - added here: d750da6

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants