Clicking on button refreshes page and forces scrolling to the bottom

Hello everyone! In my team, we’re developing a chatbot app. We would like to sometimes show some buttons to the user (e.g., with suggested prompts or download buttons). The problem is that everytime* you click on a button, the app page appears to refresh and scrolls to the bottom (which is not that big of an issue, but is still annoying). The minimum code example is provided below (the hello prints act as a replacement for a chat conversation here; the idea is that clicking on a button with suggested prompts inserts that prompt into the st.chat_input’s text field). Was wondering if there is a workaround for this, any help would be appreciated!

(*): It actually happens once per submitting user message in st.chat_input and clicking the send button, i.e., whenever you send a message using st.chat_input and click on e.g. a st.button (e.g. such as those with suggested prompts in the code below), the above issue takes place. Afterwards, however, you can click on buttons as much as you like, and that problem won’t appear at all, until you send another message using st.chat_input.

Streamlit version: 1.29.0

import streamlit as st

print('app rerun')

st.write('hello ' * 2000)

_ = st.chat_input('Enter your message:')

def inject_text_into_chat_input(msg: str):
    """
    Function to be called when the user clicks on a suggestion button. We have to resort to using JS code here, as `st.chat_input()` does not natively support setting
    a value in the text field yet.

    Code is taken from here: https://github.com/streamlit/streamlit/issues/7166#issuecomment-1751680409
    """

    js = f"""
        <script>
            function insertText(dummy_var_to_force_repeat_execution) {{
                var chatInput = parent.document.querySelector('textarea[data-testid="stChatInput"]');
                var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
                nativeInputValueSetter.call(chatInput, "{msg}");
                var event = new Event('input', {{ bubbles: true}});
                chatInput.dispatchEvent(event);
            }}
            insertText(42);
        </script>
    """
    st.components.v1.html(js)

for i in range(5):
    msg = f'Button {i}'
    st.button(msg, on_click=inject_text_into_chat_input, args=[msg])

Hey, I am going through the same issue, did you find a fix?

Hi, no, unfortunately, not, which is one of the reasons we’re considering switching to something else instead of Streamlit for production :frowning:

Streamlit has launched the st. experimental_fragment component, and I have tried to solve the problem you raised. streamlit is growing.:point_down:

import streamlit as st

print('app rerun')

st.write('hello ' * 300)
st.write('hello ' * 300)

def inject_text_into_chat_input(msg: str):
    """
    Function to be called when the user clicks on a suggestion button. We have to resort to using JS code here, as `st.chat_input()` does not natively support setting
    a value in the text field yet.

    Code is taken from here: https://github.com/streamlit/streamlit/issues/7166#issuecomment-1751680409
    """

    js = f"""
        <script>
            function insertText(dummy_var_to_force_repeat_execution) {{
                var chatInput = parent.document.querySelector('textarea[data-testid="stChatInput"]');
                var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
                nativeInputValueSetter.call(chatInput, "{msg}");
                var event = new Event('input', {{ bubbles: true}});
                chatInput.dispatchEvent(event);
            }}
            insertText(42);
        </script>
    """
    st.components.v1.html(js)

# Fragment loading👇
@st.experimental_fragment
def test():
    for i in range(5):
        msg = f'Button {i}'
        st.button(msg, on_click=inject_text_into_chat_input, args=[msg])
    
_ = st.chat_input('Enter your message:')

test()

st.write('hello ' * 100)
3 Likes

Thanks man, this solution works perfectly for me as well.
You just solved my 8 hours long issue

1 Like

Hi, thanks a lot! Seems to be solving the issue for me as well :slight_smile:

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.