I have multiselect and text area input inside st.form and st.form_submit_button. After an output has been generated (selected input option, entered text and clicked the “Extract data” button) I would like the output to be displayed until the “Extract data” button is clicked on again. However, it seems that changing input in multiselect causes the app to re-run and clear the output before clicking the button.
Below is an example of the code
# Import libraries
import streamlit as st
from time import sleep
# User input
with st.form('input'):
selected_options = st.sidebar.multiselect(
'Select option:', ['Option1', 'Option2', 'Option3'], default='Option1')
text = st.text_area("Paste text here", height=350)
submit_button = st.form_submit_button(label="Extract data")
# Extract data on submit
if submit_button:
# Check that text field is not empty
if not text.strip():
st.error('WARNING: Please enter text')
else:
with st.spinner(text = 'Extracting information...'):
sleep(3)
st.write('You selected: {}'.format(selected_options))
Python 3.8.0
Streamlit 1.11.1
I am using conda on Windows 10
Chrome Version 103.0.5060.134 (Official Build) (64-bit)
HI @Jurgita! Thanks for your question. It’s a big hard to be sure of what the indentation of your code should be – is this right?
import streamlit as st
from time import sleep
with st.form('input'):
selected_options = st.sidebar.multiselect('Select option:', ['Option1', 'Option2', 'Option3'], default='Option1')
text = st.text_area('Paste text here', height=350)
submit_button = st.form_submit_button(label='Extract data')
if submit_button:
# Check that text field is not empty
if not text.strip():
st.error('WARNING: Please enter text')
else:
with st.spinner(text = 'Extracting information…'):
sleep(3)
st.write('You selected: {}'.format(selected_options))
One way to save the state is using session_state. I tried this code and seems to be what you need:
if "option" not in st.session_state:
st.session_state["option"] = None
with st.form("input"):
selected_options = st.sidebar.multiselect(
"Select option:", ["Option1", "Option2", "Option3"], default="Option1")
text = st.text_area("Paste text here", height=350)
submit_button = st.form_submit_button(label="Extract data")
if submit_button:
# Check that text field is not empty
if not text.strip():
st.error("WARNING: Please enter text")
else:
with st.spinner(text = "Extracting information…"):
sleep(3)
st.session_state["option"] = selected_options
st.write("You selected: {} - inside submit_button".format(selected_options))
st.write(text)
if st.session_state["option"] is not None:
st.write("You selected: {} - outside submit_button".format(st.session_state["option"]))
However, it seems that changing input in multiselect causes the app to re-run and clear the output before clicking the button.
Yes, this is a fundamental property of the Streamlit architecture. You can use cache, session_state or IO operations to create an state machine or applications that preserve the state and other logics. I recommend to read this comment that is related about this characteristic
Hi @blackary - apologies for the messy formatting. What you have posted is correct, and I have now also updated the code in my original question.
It seems to me that there is a bug with st.sidebar.multiselect. I don’t get this issue if I:
move multiselect from sidebar to the top of the page - replace st.sidebar.multiselect with st.multiselect.
Re-write the code using ‘with’ notation:
# User input
with st.form('input'):
with st.sidebar:
selected_options = st.multiselect('Select option:', ['Option1', 'Option2', 'Option3'], default='Option1')
text = st.text_area("Paste text here", height=350)
submit_button = st.form_submit_button(label="Extract data")
@Jurgita Huh. That’s pretty interesting. I’m not sure what’s going on there – some interaction between the form context manager and the sidebar context manager, I suppose. It does seem like there’s some unintended behavior there. My suggestion, if you want the selected text to always be shown, then @fhtsibuya’s suggestion of using session state to cache whatever was previously extracted, and then display it outside the if submit_button: block is a good idea. When you have some set of data to be saved across app runs, then session_state is often a good choice for storing that data.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.