Retyping in the text area reloads the page instead of outputting the text after button is clicked

Summary

The app has an input area to type text. When the submit button is clicked then the user input text gets written in the screen with the text appearing in the text area. So the user can input new text in the text area and can see the output. It works fine. But there are two buttons as examples for the users. When these buttons are clicked then the text of the button gets written in the screen along with the text area. But when I type something new and click the submit button then the app goes back to the initial state and does not output anything.

Steps to reproduce

Code snippet:

import streamlit as st 

cont1 = st.empty()
with cont1.container():
    prompt = st.text_area("Text",placeholder="prompt",key='promptKey',label_visibility='hidden')
    submit_button = st.button('Submit ▶')

cont2 = st.empty()
with cont2.container():
    sample_question = '<p style="font-family:sans-serif; color:Black; font-size: 18px; position: relative; top: 20px">Examples</p>'
    st.markdown(sample_question, unsafe_allow_html=True)

    st.markdown("""<hr style="height:5px;border:none;color:#333;background-color:#333;" /> """, unsafe_allow_html=True)

    
    col1,col2 = st.columns(2)
    with col1:
        buttonName1 = "Hello!"
        button1 = st.button(buttonName1)

    with col2:
        buttonName2 = "How are you?"
        button2 = st.button(buttonName2)

def helpButtons(buttonName):
    cont1.empty()
    cont2.empty()
    buttonPrompt = st.text_area("",value=buttonName)
    submit_button3 = st.button('Submit',key='s3')
    st.write(buttonPrompt)
    if submit_button3:
        cont1.empty()
        cont2.empty()
        submitPrompt = st.text_area("", value=buttonPrompt)
        submit_button4 = st.button('Submit',key='s4')
        st.write(submitPrompt)


if prompt:
    cont1.empty()
    cont2.empty()
    prompt = st.text_area("",value=prompt)
    submit_button2 = st.button('Submit')
    st.write(prompt)
else:
    if button1 | button2:
        if button1:
            helpButtons(buttonName=buttonName1)
        elif button2:
            helpButtons(buttonName=buttonName2)

Expected behavior:

When the example button “Hello!” is pressed then “Hello” gets outputted in the screen with the text area having the text “Hello!”. Then when I change the text to “Hey!” from “Hello!” and click the submit button then the output will be “Hey!”

Actual behavior:

When the example button “Hello!” is pressed then “Hello” gets outputted in the screen with the text area having the text “Hello!”. Then when I change the text to “Hey!” from “Hello!” and click the submit button then the app returns to the initial state (like reloads the homepage) and there is no output of the text “Hey!”

Debug info

  • Streamlit version: 1.17.0
  • Python version: 3.9.13
  • Browser version: Microsoft Edge (Version 109.0.1518.69 (64-bit))

Any help is appreciated, thank you!

Hi @azzi welcome to the community! :wave:

Have you tried to use st.form? It seems that you are looking for something like in this example?

Actually, my question is not similar to the example you mentioned. If you reproduce my code, then click the example button with the text “Hello!”, it prints “Hello!” in a text_area which I want. But afterwards if you type something on that same text_area by erasing “Hello!” then the app gets reloaded which I don’t want. Instead I want the newly typed text to get printed with the text_area.

Thank you for your reply!

Hi @azzi thank’s for explanation. It is still a little bit unclear for me what you would like to achieve at the end.

Some comments:

  1. As you probably know streamlit reruns application from top to bottom on user interaction
  2. To save state of variables you may use st.session.state. Here you can find documentation and explanation in a tutorial from @asehmi

Please note that in your code you are creating three separate text forms which values are stored separately.


import streamlit as st

def callback():
    st.write("callback triggered")

cont1 = st.empty()
with cont1.container():
    st.write("This is a first text field")
    prompt = st.text_area(
        "Text", placeholder="prompt", key="promptKey", label_visibility="hidden"
    )
    st.session_state
    submit_button = st.button("Submit ▶")

cont2 = st.empty()
with cont2.container():
    sample_question = '<p style="font-family:sans-serif; color:Black; font-size: 18px; position: relative; top: 20px">Examples</p>'
    st.markdown(sample_question, unsafe_allow_html=True)

    st.markdown(
        """<hr style="height:5px;border:none;color:#333;background-color:#333;" /> """,
        unsafe_allow_html=True,
    )

    col1, col2 = st.columns(2)
    with col1:
        buttonName1 = "Hello!"
        button1 = st.button(buttonName1)

    with col2:
        buttonName2 = "How are you?"
        button2 = st.button(buttonName2)


def helpButtons(buttonName):
    cont1.empty()
    cont2.empty()
    st.write("This is a third text field")
    buttonPrompt = st.text_area("", value=buttonName, key="third_form")
    st.session_state
    submit_button3 = st.button("Submit", key="s3")
    if submit_button3:
        cont1.empty()
        cont2.empty()
        submitPrompt = st.text_area(
            "",
            value=buttonPrompt,
            key="second_form",
            on_change=callback,
        )
        submit_button4 = st.button("Submit", key="s4")


if prompt:
    cont1.empty()
    cont2.empty()
    st.write("This is a second text field")
    prompt = st.text_area("", value=prompt, key="second_form")
    st.session_state
    submit_button2 = st.button("Submit")
else:
    if button1 | button2:
        if button1:
            helpButtons(buttonName=buttonName1)
        elif button2:
            helpButtons(buttonName=buttonName2)

I have been trying to use session state to fix this problem but not being able to.