Sometimes, resetting a form in Streamlit can feel more challenging than it should be. The default option, clear_on_submit=True
, doesn’t always work for every scenario. Here are some common challenges:
- Complex forms with reruns: If your form uses dialog boxes or other elements that trigger a rerun of the app, you unintentionally lose input values.
- Not using
st.form_submit_button
: If your form doesn’t usest.form_submit_button
, theclear_on_submit
feature won’t work at all. - Using
st.form_submit_button
with additional logic: If you perform extra processing, such as input validation or saving data to a database, the form may reset before you’re done with the data.
What seems like a simple task can quickly become frustrating. I explored many posts on the Streamlit Community forum, but none of the solutions worked for my use case.
My Approach: Simple, Scalable, and Effective
The solution is to break the form into two parts. By separating the form logic, you can control when the form is displayed and reset it as needed. This approach allows you to “re-render” the form on demand, effectively resetting it without losing control over your application flow.
Here’s the approach I used, simplified into an example scenario.
The Idea
Instead of relying on clear_on_submit
, you can:
-
Track Your Form State with
st.session_state
:
Usest.session_state
to store essential variables that dictate which form or step the user is on. -
Control What’s Displayed Based on State:
For example, you might:- Show a “Setup” form if
st.session_state["form_loaded"]
is not set. - Show your main form if
st.session_state["form_loaded"]
is True.
- Show a “Setup” form if
-
Resetting the Form by Clearing Session Keys:
When the user wants to reset, just remove the session keys and callst.rerun()
.
A Quick Example
Initial State:
if "form_loaded" not in st.session_state:
st.session_state["form_loaded"] = False
#Loading the Form:
if not st.session_state["form_loaded"]:
if st.button("Load Form"):
st.session_state["form_loaded"] = True
st.rerun()
else:
st.write("Here's your form!")
# ... form fields and submit button ...
#Resetting the Form:
if st.button("Back"):
# Remove the key that shows the form
del st.session_state["form_loaded"]
st.rerun()
In this example:
- Before loading,
form_loaded
isFalse
, so the user sees a “Load Form” button or a landing view. - After clicking “Load Form”,
form_loaded
becomesTrue
and the main form appears. - If they hit “Back,” we delete
form_loaded
and rerun, returning to the initial screen.
Why This Works
- By using
session_state
, you treat certain keys as “flags” that determine what part of your app is shown. - Removing these keys resets the state back to an earlier form of your app.
- Here’s a bug with Streamlit form - Even if you remove all the Session state variables, the form values entered by user a still visible even after the st.rerun. And hence, by having an initial landing form/view - we force Streamlit to re-render the form.
st.rerun()
immediately re-executes the script, making the UI reflect the cleared state.
Key Takeaways
- Break form into two parts !
- Use
st.session_state
to control your app’s flow. - Delete session keys to revert to a previous state, effectively “resetting” your form.
- Combine these tricks with
st.rerun()
to refresh the UI instantly.
This method is flexible and can be adapted to multiple-step forms, complex states, or any time you need to reset user input back to a known starting point.
Happy to receive input and suggestions from the community !
PS - Thanks for the Streamlit team for this amazing tool.