Is there a way to disable st.form_submit_button after input?

Hi there. I am new to Streamlit and I am trying to make an experimental webpage that will remember the name of the user. This will be done through an input form and a submit button. The name value will be stored with st.session_state. But then I want it to disable submit button, so users won’t be allowed to make a second input or a duplicate. But I am stuck. Any ideas?

That’s my code so far

Code snippet:

with st.form("myform"):
    name=st.text_input("Enter your name below:")
    submit_button=st.form_submit_button("Submit")
    
    if submit_button:
        st.info("You have entered: "+name)
    
        if "my_input" not in st.session_state:
            st.session_state["my_input"]=name
        else:
            st.session_state["my_input"]=name

Code works fine, but it allows duplicates and second inputs.

Expected behavior:

I want the submit button to be disabled after the very first input. If there is a way for the text to “freeze”, that would be awesome too!

Hi @Ronnie_Nolan,

Welcome to the Streamlit Community! :wave: :partying_face:

The st.form_submit_button docs say the command has two relevant parameters:

  • on_click (callable): An optional callback invoked when this button is clicked.
  • disabled (bool): An optional boolean, which disables the button if set to True. The default is False. This argument can only be supplied by keyword.

We can make use of both of them to achieve the behavior you want. In this example:

  1. We first initialize a session state variable called disabled to False and pass that to the form submit button’s disabled parameter.
  2. Next, we define a function disable() that sets st.session_state.disabled to True.
  3. Pass the disable function to the on_click parameter of the form submit button, so that when the button is clicked, the disable() function is executed, and that in-turn disables the button

Code

import streamlit as st

# Disable the submit button after it is clicked
def disable():
    st.session_state.disabled = True

# Initialize disabled for form_submit_button to False
if "disabled" not in st.session_state:
    st.session_state.disabled = False

with st.form("myform"):
    # Assign a key to the widget so it's automatically in session state
    name = st.text_input("Enter your name below:", key="name")
    submit_button = st.form_submit_button(
        "Submit", on_click=disable, disabled=st.session_state.disabled
    )

    if submit_button:
        st.info("You have entered: " + st.session_state.name)

Output

disable-form-submit-button

Happy Streamlit-ing! :balloon:
Snehan

1 Like

Thank you very much. That was very helpful. I finally used st.session_state the way you recommended but also at some other point in my code, because I needed the name input to be stored for further use in the page and in a local excel file. I had no clear understanding of that, but it works now. I then eliminated the initial blank inputs with a simple if statement. Here’s the code.

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

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

with st.form("myform"):
    name=st.text_input("You only have one chance:",
                       key="name",placeholder="Enter your name here")
    submit_button=st.form_submit_button("Submit",on_click=disable,
                                        disabled=st.session_state.disabled)

    if submit_button:
        st.info("Username submited: "+st.session_state.name)
    
        if "my_input" not in st.session_state:
            st.session_state["my_input"]=name
            if name!="":
                vis=[name]
                df=pd.DataFrame(vis)
                with pd.ExcelWriter(visitors,mode="a",engine="openpyxl",
                                    if_sheet_exists="overlay") as writer:
                    df.to_excel(writer,index=False,header=False,
                                startrow=writer.sheets["Sheet1"].max_row)
1 Like

Hi all,

I have a similar problem. I used this example: Disable button during on_click function evalution to control the st.buttons.

But this does not work for st_submit_buttons. The here presented way is ok, if you shall have only one chance. But it does not work, if the st_submit_button shall activated / deactivated by callback / key.

Is there any other possibility to control st_submit_button from anywhere of the code?