Auto-collapse an expander in a form

Hi all, I’ve tried searching through the forums and found a couple related posts that weren’t quite what I wanted, so I’ll post another here.

Desired behavior:

  • In a form I want toggle-able optional inputs, that resets (and hides) after form submission


  1. Using a checkbox, and an if-statement right after the checkbox that creates the new inputs of the checkbox is clicked. From my understanding this is common practice outside of a form, but within a form this doesn’t work b/c nothing is evaluated until the submit button is pressed, and callbacks aren’t allowed within a form.
  2. Tried using an expander. However, the expander stays open after submitting the form, when I want the expander to reset to closed. For reference, I do set clear_on_submit = True.



Hi @EqualAPriori

Thanks for your question, could you share with us a working example code that reproduces your error so that we can see how to help.


Best regards,

Hi @dataprofessor

Thanks! I have a related but different problem now, where a button only closes the expander the first time. But if one manually opens the expander, the button no longer works:

import streamlit as st

st.write("The button can only close the expander the first time! And not after the expander is manually opened.")

if "expander_state" not in st.session_state:
    st.session_state["expander_state"] = True

def toggle_closed():
    # <potentially do other actions>
    st.session_state["expander_state"] = False

st.button("do stuff then close expander",on_click=toggle_closed)

with st.expander("test expander",expanded = st.session_state["expander_state"]):
    st.write("expander is open")

It seems to me that buttons can only toggle expanders if the expanded keyword in the expander definition changes.

The challenge is that one can’t ensure that the expander is only opened by a button that toggles the expander definition (indeed, the intuitive thing for people is to open the expander directly instead of via some other toggling button, which is also a clunky UX experience).


EDIT: mathcatsand helped me with this here: The key was to force a re-definition and rerun, and to put in a time delay to ensure the front-end and back-end sync up.