I have a form that includes a text_area and a few other controls. I’m trying to update the content of the text_area in a callback.
What works:
If I define a key argument for the text_area and get in the callback via the on_click argument of the submit_button I can do something like st.state_session.my_key = foo to update the the text of the text_area However, I can’t pass arguments (values from other components of the form) to the callback correctly because I run into the issue that’s covered in the FAQ where arguments are always one step behind. I’m a bit surprised because these components do not have a key and the FAQ says this is an issue when using st.session_state and doesn’t say anything about forms but apparently the same thing applies to all elements in a form?
What doesn’t work:
I noticed some of the examples in the doc use the pattern below:
...
submit = st.form_submit_button(...)
if submit:
callback_func(a,b,c)
...
This has the benefit that the argument passed to the callback are correct but for some reasonu pdating the text_area in the callback now fails:
streamlit.errors.StreamlitAPIException: `st.session_state.my_text_area` cannot be modified after the widget with key `my_text_area` is instantiated.
Streamlit won’t have knowledge of any changes made to inputs inside a form until it’s submitted. This is the design of the form element. If you want to update a widget based on some action, that action will have to be outside of a form (either the submission of the form or something else entirely). Please can you describe the workflow you are trying to implement specifically so I can understand what you are looking for? I can probably mock up a simple example for you. (By the way, if you put keys in all your form widgets, you can get them from session state inside of the callback, which I gather is what you’re going for…)
So this almost work in the sense that the text_area in the form gets updated but it’s always one step behind in terms of values. I thought callback runs first before the whole script is rerun which is why I updated the session_state in the callback and hoped that then the text_area is redrawn but I must be missing something.
If you want to do something in a callback with a freshly submitted value, you have to grab it by its key within the callback and can’t have it as an argument provided with the on_click or on_change function.
I added a numeric version, too, in case it was of interest.
import streamlit as st
# Added a numeric value that can be incremented, just as an example
if 'result' not in st.session_state:
st.session_state.result = 0
# No argument in the callback; current value to be added is grabbed directly from session state
def my_callback():
# Get submitted value
temperature = st.session_state.temperature
# Append string to key of widget
st.session_state.my_key = st.session_state.my_key + str(temperature)
# Add value to non-widget key in session state
st.session_state.result += temperature
with st.form("foo"):
st.text_area("label", key="my_key")
st.markdown(f'#### The total temperature is {st.session_state.result:.2f}.')
temp = st.slider(
"Temperature",
min_value=0.0,
max_value=100.0,
value=1.0,
key='temperature'
)
# Option 1:
submit = st.form_submit_button(
"compute",
on_click=my_callback
)
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.