Disable interactables after suitable interaction

Summary

I want to disable some parts of my app after users provided fitting input but I cannot seem to make it work even though I followed (to my knowledge) other tutorials on this.

Steps to reproduce

Code snippet:

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

st.markdown('This is a simple example')

uploaded_file = st.file_uploader("Select your data", disabled=st.session_state.disabled)
if uploaded_file is not None:
    st.text('You uploaded the file:')
    st.write("Filename: ", uploaded_file.name)

    st.text('Add some text.')
    text_input = st.text_input("Add your text", disabled=st.session_state.disabled)

    if text_input != "": #here I want to add more checks to verify the input
        st.text(f"You wrote {text_input}")

        with st.spinner('Wait for the process to finish...'): # in this I do something with input and file
            st.session_state["disabled"] = True # while this runs, I want the upload and input field to be locked
            time.sleep(10)
        st.session_state["disabled"] = False

If applicable, please provide the steps we should take to reproduce the error or specified behavior.

Expected behavior:

When the user presses enter to lock their input, I want to do some checks which are, if the input is correct, used to call some other function. While that function runs, I want the interactable fields (uploader and input field) not to be interactable until after it finished.

Actual behavior:

Everything works but not the disabling/enabling
ETA: I just found out that if I change the text_input while the spinner is running, it disables the file upload and removes the file and therefore everything after the if-statement

The issue you’re facing is related to how Streamlit’s session state and disabling of widgets work. When you set the disabled property of a widget to st.session_state.disabled, changing the value of st.session_state.disabled will not automatically update the disabled state of the widget. Instead, you need to explicitly set the disabled property of the widget whenever you change the value of st.session_state.disabled.

To achieve the desired behavior of disabling the file uploader and text input fields while the spinner is running, you can modify your code as follows:

import streamlit as st
import time

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

st.markdown('This is a simple example')

uploaded_file = st.file_uploader("Select your data", disabled=st.session_state.disabled)
if uploaded_file is not None:
    st.text('You uploaded the file:')
    st.write("Filename: ", uploaded_file.name)

    st.text('Add some text.')
    text_input = st.text_input("Add your text", disabled=st.session_state.disabled)

    if text_input != "":
        st.text(f"You wrote {text_input}")

        if st.button("Process Data"):
            with st.spinner('Wait for the process to finish...'):
                st.session_state["disabled"] = True
                time.sleep(10)
            st.session_state["disabled"] = False

In this code, I’ve made the following changes:

  • Instead of using st.session_state["disabled"] as the disabled property of the widgets, I’ve set it only during widget creation.
  • Added a button labeled “Process Data” to initiate the data processing.
  • When the button is clicked, the spinner is shown, and st.session_state["disabled"] is set to True to disable the widgets.
  • After the processing is complete, st.session_state["disabled"] is set back to False to enable the widgets again.

By using a separate button to trigger the data processing, you can ensure that the widgets remain disabled while the processing is ongoing.