enabling interactive elements after disabling them

HI Streamlit community,

I have a question:

So I want to run a pretty large analysis via a Streamlit based GUI, and I now want to disable the users from changing any variables during the analysis, but after the analysis is done it should lift the disabling of the interactive elements.

import streamlit as stimport time

if "disabled" not in st.session_state:st.session_state.disabled = False

def disable():
    st.session_state.disabled = True

def enable():
    st.session_state.disabled = False

st.button("Run process",disabled=st.session_state.disabled,on_click=disable)


#Whatever process takes placetime.sleep(10)

st.toast("done")

#now set the session state back to False

Because just adding the enable function at the end does update the variable but not the rendering like it does on the on_click from the st.button. So is there a way to update the rendering of what is disabled and what is enabled again?

import streamlit as st
import time

if "disabled" not in st.session_state:
    st.session_state.disabled = False

if "run_requested" not in st.session_state:
    st.session_state.run_requested = False

def start_run():
    st.session_state.disabled = True
    st.session_state.run_requested = True

st.button(
    "Run process",
    disabled=st.session_state.disabled,
    on_click=start_run
)

if st.session_state.run_requested:
    st.toast("process")
    st.session_state.run_requested = False

    time.sleep(10)

    st.toast("done")

    st.session_state.disabled = False

    st.rerun()

 

I considered something like this, but this reruns and does not keep the “done” toast or other instance specific outputs. And as I understand, after the rerun you can’t just add the toast there because the rerun stops further code processing. Anyone got any ideas?

Hey, thanks for your thoughtful question and for sharing your code! :balloon: You’re right: simply setting st.session_state.disabled = False at the end of your process won’t immediately re-enable widgets, because Streamlit only updates widget states on rerun. Using st.rerun() after your process does reset the UI, but it also clears transient outputs like st.toast() since the script restarts from the top and doesn’t “remember” the toast.

The recommended approach is to save any outputs you want to persist (like a “done” message) in st.session_state, then display them after rerun. For example, set a flag like st.session_state.show_done = True before calling st.rerun(), and then conditionally show the toast at the top of your script if that flag is set. This way, the UI updates and your message persists for at least one rerun cycle. See the code below for a pattern that works well:

import streamlit as st
import time

if "disabled" not in st.session_state:
    st.session_state.disabled = False
if "run_requested" not in st.session_state:
    st.session_state.run_requested = False
if "show_done" not in st.session_state:
    st.session_state.show_done = False

def start_run():
    st.session_state.disabled = True
    st.session_state.run_requested = True

st.button(
    "Run process",
    disabled=st.session_state.disabled,
    on_click=start_run
)

if st.session_state.run_requested:
    # Simulate long process
    time.sleep(10)
    st.session_state.run_requested = False
    st.session_state.disabled = False
    st.session_state.show_done = True
    st.rerun()

if st.session_state.show_done:
    st.toast("done")
    st.session_state.show_done = False

This pattern ensures widgets are disabled during processing, re-enabled after, and your “done” message appears after rerun. For more details and variations, see this forum thread and this related discussion. If you run into issues, please share a minimum reproducible example and let the community jump in!

Sources:

Hey,

That is indeed a fix for my problem! Thank you very much for your response and I wish you a good rest of your day!