St.selectbox with only one entry, auto-select the only available option

Hi, I’m creating a page with multiple selectboxes

The options available in the second selectbox are influenced by the option that the user picks in the first selectbox:

st.selectbox("SelectBox 1", ["choice A", "choice B"], index=None, key="selectbox1")
selectbox1_pick = st.session_state["selectbox1"]

if selectbox1_pick is None:
    selectbox2_options = []
elif selectbox1_pick == "choice A":
    selectbox2_options = ["only one choice"]
elif selectbox1_pick == "choice B":
    selectbox2_options = ["Alpha", "Beta", "Gamma"]
else:
    raise ValueError

st.selectbox("SelectBox 2", selectbox2_choices, 
    index=0 if len(selectbox2_options) == 1 else None, key="selectbox2")

The behavior I am trying to achieve is this:

If the user picks choice A from selectbox1, then selectbox2 will have only one available option: only one choice. Since this is the only available option, it should be auto-selected by the code in order to prevent the user from having to click on the selectbox and choose the only option that is available.

I am trying to get this behavior with

index=0 if len(selectbox2_options) == 1 else None

when defining selectbox2. However, the second selectbox always defaults to choose an option instead of defaulting to only one choice in case selectbox1 is set to choice A.

Before selecting anything in SelectBox1:
image

After picking choice A this happens:
image
(notice that SelectBox2 is still displaying Choose an option)

What I would like to happen instead is that SelectBox2 automatically selects the only available option:
image

How can I accomplish the auto-select behavior in the case where the number of options is exactly 1?

Shouldn’t this be len(selectbox2_options) == 1?

Indeed, thanks for noticing this. It does not change the behavior though.

Interesting, it works if you remove the key parameter from the second selectbox.

I think it might be because of a typo in your code – I see that you use selectbox2_choices and selectbox2_options, and it works fine for me if I make those both the same.

import streamlit as st

st.selectbox("SelectBox 1", ["choice A", "choice B"], index=None, key="selectbox1")
selectbox1_pick = st.session_state["selectbox1"]

if selectbox1_pick is None:
    selectbox2_options = []
elif selectbox1_pick == "choice A":
    selectbox2_options = ["only one choice"]
elif selectbox1_pick == "choice B":
    selectbox2_options = ["Alpha", "Beta", "Gamma"]
else:
    raise ValueError

st.selectbox("SelectBox 2", selectbox2_options, 
    index=0 if len(selectbox2_options) == 1 else None, key="selectbox2")

You can see it here.

Thanks for the code. I would expect that selectbox2 defaults to (=automatically selects) only one choice if selectbox1 is set to choice A. selectbox2 remains at choose an option though.
Is it possible to auto-select only one choice in selectbox2 when choice A is picked in selectbox1?

If you remove the key parameter in the second selectbox, it behaves as you expected.

Without key With key
selectboxes_1 selectboxes_2

Ah yeah, that seems to be the trick

That’s curios. Thanks for spotting that!
How do I retrieve the user-selected value without defining/knowing the key?

You can assign the return value of the st.selectbox to a variable

user_selection = st.selectbox(...)

or to the session state

st.session_state["user_selection"] = st.selectbox(...)

Ah, I see. Thanks!

Sorry I have another follow-up question though: when I define a selectbox with a key=<name of this selectbox>, I can clear the selection via a reset button that executes st.session_state["<name of this selectbox>"] = None if pressed.

If the selectbox does not have a user-defined key though, I am curios how I could reset it?

In that case you do need the user-defined key. The fact that setting a key does not allow you to change the selectbox’s index programmatically should be considered a bug imo.

There is a somewhat related github issue:

I think you should keep the key and set the widget state by changing session state instead of the index. But I haven’t tried your code so I might be missing something.