Control st.toggle() using st.button()

I am testing a very simple streamlit app with a toggle and a button. Specifically, I want to use st.toggle and have a st.button that, when clicked, switches this toggle off. The toggle is on by default.

The problem I am facing is that the button works fine to disable the toggle on the first click. Now if I turn the toggle on manually and click the button, it does not switch the toggle off. Further, turning the toggle on/off manually is taking two mouse clicks. Is there something about session_state I am missing in my code? Thanks for any advice!

Code below with comments. Deployed locally. Python v3.12 and Streamlit v1.34.

import streamlit as st

st.title('Streamlit Toggle App')

# Initialize or retrieve the current state of the toggle
if 'toggle' not in st.session_state:
    st.session_state.toggle = True  # Default to on

# Function to switch off the toggle
def switch_off_toggle():
    st.session_state.toggle = False

# Display the toggle with its current state
toggle = st.toggle("Toggle", value=st.session_state.toggle)

# Display the button, which when clicked, will call the function to switch off the toggle
btn = st.button("Switch Off Toggle", on_click=switch_off_toggle)

# Update the toggle state based on user interaction
st.session_state.toggle = toggle

# Optional: Display the current state of the toggle
st.write("Toggle is currently:", "On" if st.session_state.toggle else "Off")

Hi @saurabh-khanna

Typically, if youโ€™re encountering that it takes 2 clicks to see a change, itโ€™s most likely that youโ€™ll need to apply session state with callback function. Could you try using the switch_off_toggle function on st.toggle() and see if that works?

When you want to programmatically control widgets, use key to tie their value directly to Session State.

toggle = st.toggle("Toggle", key="toggle")
1 Like

I think this is a good way to accomplish what youโ€™re looking for

import streamlit as st

if "toggle" not in st.session_state:
    st.session_state.toggle = True  # Default to on

if "toggle_key" not in st.session_state:
    st.session_state.toggle_key = 1

def toggle_toggle():
    st.session_state.toggle = not st.session_state[st.session_state.toggle_key]
    st.session_state.toggle_key += 1

toggle = st.toggle(
    "Toggle", value=st.session_state.toggle, key=st.session_state["toggle_key"]

st.button("Toggle Toggle", on_click=toggle_toggle)

One trick is that, to make sure that the userโ€™s selection gets overridden, you actually want to change the key that is associated with the toggle, so that it gets created afresh.