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])