Catch any input into text area to enable download button?

I have a text area and a download button based on the input for the text area. Default streamlit behavior is for the user to press ctrl/cmd + enter or to focus on a different element from the textarea.

The goal is to have a button that is disabled until any character is in the textarea element. Currently, this only works with ctrl/cmd+enter to have the disable property changed to enabled for the button.

With a standard st.button, I can write a components hook that sees events triggered by individual keystrokes. However, st.download_button does not catch this.


const doc = window.parent.document;

const textarea = Array.from(doc.querySelectorAll('textarea'))[0];
const buttons = Array.from(doc.querySelectorAll('button'));

const submit = buttons.find(el => el.innerTexas === 'Download');

textarea.addEventListener('input', event => {
if ( > 0) {
  submit.disabled = false;
} else {
  submit.disabled = true;

then, later:

download_read = st.button("Download", key="Download", type = 'primary')

Replacing the button with download_button does not work – any ideas?

download_read = st.download_button(
  data = data_generation_function(text_area_input),

Hi @tom_roderick

You can use the disabled parameter for either st.button or st.download_button in order to disable the button until the text has been entered into the st.text_area widget.

An example of this in use is the following code:

where the st.chat_input is disabled when st.text_input is blank.

In your use case, this may look something like:

txt_input = st.text_area("Enter text", "")
btn = st.button("Click me", disabled=not txt_input)

where the button will be activated once text is entered.

Hope this helps!

1 Like

I appreciate the input. In this case, text_area doesn’t capture input text until control/command + enter is pressed, or the text area widget is no longer focused.

My workaround works for a standard button, but something is preventing the download_button widget from accessing.

No worries, I’ve decided to use two buttons as a solution to continue moving forward and to figure out how to bridge our custom React widget component library.