Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting placeholder for st.multiselect #6901

Merged
merged 10 commits into from Jul 10, 2023

Conversation

fhiroki
Copy link
Contributor

@fhiroki fhiroki commented Jun 26, 2023

Describe your changes

As described here, st.multiselect widgets cannot change placeholders.
CSS hacks solve the problem, but it is tricky, and will not work if the DOM structure changes in the future.
Therefore, I would like to be able to change placeholders in the official way.

GitHub Issue Link (if applicable)

#4750

Testing Plan


Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

Copy link
Collaborator

@vdonato vdonato 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 the contribution @fhiroki!

The code here mostly looks good to me, but I left a few small comments with some things that should be addressed. Additionally, it'd be great to add a few tests in lib/tests/streamlit/elements/multiselect_test.py and frontend/src/lib/components/widgets/Multiselect/Multiselect.test.tsx that ensure that the default values are set as expected and can be changed. An e2e test in e2e/scripts/st_multiselect.py and e2e/specs/st_multiselect.spec.js would also be nice to have.

Another thing is that, aside from the code itself, we'll want to be sure that we want to do this from a product perspective. Adding this feature seems reasonable to me, but I'll defer to @jrieke and @sfc-gh-jcarroll for a final decision on adding new parameters to the st.multiselect API.

lib/streamlit/elements/multiselect.py Outdated Show resolved Hide resolved
@sfc-gh-jcarroll
Copy link
Collaborator

Nice, thanks for the contribution.

Couple questions / comments:

  • Should we add this to st.selectbox as well for consistency? Or is there a reason this is needed for multiselect but not selectbox? (could be a separate PR, just wondering if we need to file / track that if so)
  • I really don't like adding 3 params for this, it doesn't feel super Streamlit-y. I'll be much happier if we just add placeholder, but open to being convinced.
    • Am I correct in thinking that placeholder_no_options functionality is still possible in any app without this param by detecting that the options list is empty and setting the value of placeholder accordingly? Since the options list should be fixed for any given script run. If my thinking is off then maybe I can be convinced!
    • Do you have a concrete use case in mind for placeholder_no_results or was it more of a completeness thing to include it?

@fhiroki
Copy link
Contributor Author

fhiroki commented Jun 27, 2023

@vdonato
Thank you so much for the swift response. It may take some time, but I would like to add the tests you suggested.

@fhiroki
Copy link
Contributor Author

fhiroki commented Jun 27, 2023

@sfc-gh-jcarroll
Thanks for your review!

Should we add this to st.selectbox as well for consistency? Or is there a reason this is needed for multiselect but not selectbox? (could be a separate PR, just wondering if we need to file / track that if so)

Since st.selectbox requires some kind of selection by default, the need for a placeholder is less than st.multiselect. But as you say, for consistency, we can add it to st.selectbox as well.

I really don't like adding 3 params for this, it doesn't feel super Streamlit-y.

I apologize for making a suggestion that goes against the design philosophy of Streamlit. However, it would be very beneficial if it could be set on the user side, since placeholder_no_results is a message when a search result is not a hit. This seems to be a common case.

image

On the other hand, placeholder_no_options is an option added for completeness, and I don't think there are that many cases where the options list is empty, I think it can be removed.

Am I correct in thinking that placeholder_no_options functionality is still possible in any app without this param by detecting that the options list is empty and setting the value of placeholder accordingly?

I guess this parameter is for when the options list is empty at the start of Streamlit. Therefore, I don't think it is usually empty.

Removed this param with the following commit.
3c6bc86

@fhiroki
Copy link
Contributor Author

fhiroki commented Jun 27, 2023

@vdonato
As you suggested, I have added a new unit test. I apologize that I could not add e2e as it was difficult to set up a local cypress environment.
8d120db

@fhiroki fhiroki requested a review from vdonato June 27, 2023 10:27
@LukasMasuch
Copy link
Collaborator

We could also allow that all via the placeholder parameter by allowing tuples:

placeholder: str | tuple[str, str] | tuple[str, str, str]

...

# Only set no selection placeholder:
placeholder = "Select options" 

# Set no selection and no results placeholder:
placeholder = ("Select Options", "No results")

# Set no selection, no results and no options placeholder:
placeholder = ("Select Options", "No results", "No options")

This will make it a bit less discoverable that these placeholders can be updated as well, but no results / no options are anyways more niche use cases.

@sfc-gh-jcarroll What do you think?

@jrieke
Copy link
Collaborator

jrieke commented Jun 27, 2023

Super cool, thanks. I think I'm fine with merging this with a few caveats:

  1. I 100% agree with Joshua that we should only have one parameter placeholder. I get that there might be some situations where you also want to modify the "No results" message but I think a) it's less common and b) "No results" probably is at least OK for pretty much every use case. To be clear, this isn't saying this is useless! ❤️ It's just a tradeoff we need to make for every new parameter: is the added customization worth the added complexity. In the case of "No results", I don't think it is. I also don't like introducing tuples too much.

  2. Can we make the order of parameters ..., *, max_selections, placeholder, disabled, label_visibility? Then it's a bit more aligned with other widgets. (I see that we're currently having max_selections at the end already but we should have put it before disabled and label_visibility.)

  3. For st.selectbox, you're right that it currently wouldn't show up but we are actually adding the ability to initialize a selectbox with an empty selection pretty soon. So when we do that, we should probably also add the placeholder for consistency! @LukasMasuch do you think it would make sense if @fhiroki makes a separate PR for that and you just merge it whenever we do the other project? (@fhiroki only if you want to of course!)

@sfc-gh-jcarroll
Copy link
Collaborator

Yep makes sense to add selectbox support later when it's possible.

My preference as well is to keep one parameter that just takes a string for placeholder, and keep "No results" as a constant for now. One other use case for changing "No results" is localization / non-English apps but I think it would need a bigger discussion so I would prefer to not handle it one-off here.

@vdonato
Copy link
Collaborator

vdonato commented Jun 27, 2023

Thanks for adding the unit tests @fhiroki! I'm happy to help with adding some e2e tests once we've finalized the API for this (note that I'll be out of the office from Thursday to July 5, so I may be delayed in being able to help with this).

I like @LukasMasuch's suggestion with placeholder having type str | tuple[str, str] (since it seems like we've agreed that there's not much of a need to be able to customize the "No options" placeholder), but another option could be to make the type of placeholder str | dict[str, str], where a single str is the normal placeholder value, and a dict should contain the keys placeholder and no_options_placeholder (or something like that -- I don't have a strong opinion on what the keys should be). This would be a bit more human-readable than a tuple and is consistent with the API in st.set_page_config's menu_items parameter.


Can we make the order of parameters ..., *, max_selections, placeholder, disabled, label_visibility? Then it's a bit more aligned with other widgets. (I see that we're currently having max_selections at the end already but we should have put it before disabled and label_visibility.)

I don't think parameter order for kwarg-only parameters actually has any effect aside from what order the parameters will appear in the documentation, so we should be able to shuffle these around easily.

@fhiroki
Copy link
Contributor Author

fhiroki commented Jun 28, 2023

Thank you all for your suggestions. It seems strongly desired to have only placeholder param, so I have modified it as such. 94cf4b1

It's just a tradeoff we need to make for every new parameter: is the added customization worth the added complexity.

This makes a lot of sense, since the parameters close to the user must be carefully selected or the cognitive load will be high.

One other use case for changing "No results" is localization / non-English apps

Actually, I was thinking of adding placeholder_no_results mainly for non-English app, do you have plans to support localization in the future? I would also like to localize st.date_input.

I'm happy to help with adding some e2e tests once we've finalized the API for this

@vdonato Thank you for your kindness. With the simpler requirements, I'm wondering if I just modify the existing tests a bit. 071e0ed

In a separate PR, I would be happy to add a placeholder to st.selectbox too. Please let me know if it is more convenient to do this within this PR.

@LukasMasuch
Copy link
Collaborator

@fhiroki adding the selectbox placeholder in a separate PR would be the preferred path. Then we can already merge this PR for multiselect.

@fhiroki fhiroki changed the title Allow setting placeholders for st.multiselect Allow setting placeholder for st.multiselect Jun 28, 2023
Copy link
Collaborator

@vdonato vdonato left a comment

Choose a reason for hiding this comment

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

With the simpler requirements, I'm wondering if I just modify the existing tests a bit. 071e0ed

I think that should be okay given that the changes are now simpler.


This LGTM! We'll just need to make some small changes to the proto file to ensure that schema versions are backwards compatible, but aside from that this PR is ready to be merged.

The max selections that can be selected at a time.
This argument can only be supplied by keyword.
placeholder : str
An optional string to display when option is not selected.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: maybe "A string to display when no options are selected. Defaults to 'Choose an option'"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

d14d375
Thank you for the suggestion. It would be better to specify the default value.

Comment on lines 30 to 33
int32 max_selections = 9;
string placeholder = 10;
bool disabled = 11;
LabelVisibilityMessage label_visibility = 12;
Copy link
Collaborator

@vdonato vdonato Jul 7, 2023

Choose a reason for hiding this comment

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

Same comment here as in #6913 (comment) we'll need to keep tag numbers the same for existing fields and add placeholder as tag 12.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

d14d375
I understood that it is not necessary to match the order of the arguments. Thanks for telling me.

@fhiroki fhiroki requested a review from vdonato July 10, 2023 01:31
@LukasMasuch
Copy link
Collaborator

@fhiroki Thanks for the changes. Based on some changes we just merged into develop, you need to merge with develop as well and resolve some conflicts.

Copy link
Collaborator

@vdonato vdonato left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @fhiroki! I can handle merging the latest changes from develop to get rid of the merge conflicts.

@vdonato vdonato merged commit 42af76a into streamlit:develop Jul 10, 2023
47 checks passed
tconkling added a commit to tconkling/streamlit that referenced this pull request Jul 12, 2023
* develop:
  Feature: st.toast (streamlit#6783)
  Bump semver from 5.7.1 to 5.7.2 in /frontend (streamlit#6982)
  Add host communication e2e tests  (streamlit#6806)
  Re-add homepage to package.json (streamlit#6987)
  Remove unnecessary code and Add rm commands to make clean (streamlit#6980)
  Allow setting placeholder for st.selectbox (streamlit#6913)
  Allow setting placeholder for st.multiselect (streamlit#6901)
  Also use bottom padding in embedded mode for chat input (streamlit#6979)
  Feature/st lib (streamlit#6692)
  Remove unused import (streamlit#6977)
  Release 1.24.1 (streamlit#6965)
  Update st.audio/st.video docstrings (streamlit#6964)
  Slightly simplify bug report template (streamlit#6972)
  Fix baseweb warnings by using longhand properties (streamlit#6976)
eric-skydio pushed a commit to eric-skydio/streamlit that referenced this pull request Dec 20, 2023
* multiselect placeholders can be set

* destructure placeholder and placeholderNoOptions

* fix placeholder type Optional[str] to str

* remove placeholder_no_options

* add unit test

* remove placeholder_no_results and change order of parameters

* change the order of args

* update e2e test

* revert proto number and fix docs

---------

Co-authored-by: Vincent Donato <vincent@streamlit.io>
zyxue pushed a commit to zyxue/streamlit that referenced this pull request Mar 22, 2024
* multiselect placeholders can be set

* destructure placeholder and placeholderNoOptions

* fix placeholder type Optional[str] to str

* remove placeholder_no_options

* add unit test

* remove placeholder_no_results and change order of parameters

* change the order of args

* update e2e test

* revert proto number and fix docs

---------

Co-authored-by: Vincent Donato <vincent@streamlit.io>
zyxue pushed a commit to zyxue/streamlit that referenced this pull request Apr 16, 2024
* multiselect placeholders can be set

* destructure placeholder and placeholderNoOptions

* fix placeholder type Optional[str] to str

* remove placeholder_no_options

* add unit test

* remove placeholder_no_results and change order of parameters

* change the order of args

* update e2e test

* revert proto number and fix docs

---------

Co-authored-by: Vincent Donato <vincent@streamlit.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants