Summary
st.expander
retains its state after interaction with another element.
Steps to reproduce
Code snippet:
import streamlit as st
button = st.button('Button')
with st.expander('expander', expanded=False):
st.write('Hello!')
Launch and click expander, then click the button.
Expected behavior:
Expected the expander to unexpand after the button press, due to expanded=False
.
Actual behavior:
The expander remains expanded (it does unexpand when the page is refreshed, though). I understand it often makes sense to have the expansion state persist automatically, but I can’t seem to find an easy way to control the state after the first initialization.
Debug info
- Streamlit version: 1.16.0
- Python version: 3.11.0
- pyenv
- OS version: MacOS 12.5.1
- Browser version: Safari 16.0
You can achieve this behavior using st.session_state
.
import streamlit as st
# initialise a boolean attr in session state
if "button" not in st.session_state:
st.session_state.button = False
# write a function for toggle functionality
def toggle():
if st.session_state.button:
st.session_state.button = False
else:
st.session_state.button = True
# create the button
st.button("Button", on_click=toggle)
with st.expander('expander', expanded=st.session_state.button):
st.write('Hello!')
Thanks! Unfortunately this doesn’t quite solve my problem… toggling the expanded state with the button does seem to work, but I want the button to be one-directional (click it, and it unexpands the expander if it is expanded, but not vice versa).
You can either modify the toggle function so it only sets st.session_state.button = True
which would remove the reverse functionality, or you can disable or hide the button after you get your one and only click that you wish to track.