Reputation: 113965
I have a multiselectbox in the sidebar of my streamlit app. Without loss of generality:
1
and 2
simultaneouslyI would therefore like to remove 2
from the list of possible selections if 1
is selected, but streamlit seems to have no capability for this, so I tried to wrap it in a loop, which also fails (DuplicateWidgetID: There are multiple identical st.multiselect widgets with the same generated key.
):
options = [1,2,3,4,5,6,7,8,9,10]
space = st.sidebar.empty()
answer, _answer = [], None
while True:
if answer != _answer:
answer.append(space.multiselectbox("Pick a number",
options,
default=answer
)
)
options = [o for o in options if o not in answer]
if 1 in options:
if 2 in options: options.remove(2)
if 2 in options:
if 1 in options: options.remove(1)
_answer = answer[:]
Any thoughts on how I could achieve this?
Upvotes: 4
Views: 4448
Reputation: 5024
Here is one approach, provide a help on the widget, and just allow the user to select both 1 and 2 but then we have to filter out 2 if both are selected. Then you can just use the validated selection.
import streamlit as st
ms = st.sidebar.multiselect('Pick a number', list(range(1, 11)),
help='Choose either 1 or 2 but not both. If both are selected 1 will be used.')
if 1 in ms and 2 in ms:
ms.remove(2)
st.write('##### Valid Selection')
st.write(str(ms))
Hover mouse on the ?
to show the help.
Use radio button for options 1 or 2 and the rest for multiselect.
import streamlit as st
rb = st.sidebar.radio('Pick a number', [1, 2])
ms = st.sidebar.multiselect('Pick a number', list(range(3, 11)))
selected = ms
selected.append(rb)
st.write('##### Valid Selection')
st.write(str(selected))
When 1 is selected remove the 2 and then rerun to update the options. Likewise when 2 is selected remove the 1 and rerun to update the options.
import streamlit as st
init_options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
if 'options' not in st.session_state:
st.session_state.options = init_options
if 'default' not in st.session_state:
st.session_state.default = []
ms = st.sidebar.multiselect(
label='Pick a number',
options=st.session_state.options,
default=st.session_state.default
)
# If 1 is selected, remove the 2 and rerun.
if 1 in ms:
if 2 in st.session_state.options:
st.session_state.options.remove(2)
st.session_state.default = ms
st.experimental_rerun()
# Else if 2 is selected, remove the 1 and rerun.
elif 2 in ms:
if 1 in st.session_state.options:
st.session_state.options.remove(1)
st.session_state.default = ms
st.experimental_rerun()
st.write('##### Valid Selection')
st.write(str(ms))
Upvotes: 1