How would I add a JavaScript to the text_area so that it changes the function of the "tab" key?

I’m trying to modify the use of the tab in text_area, I looked for how to do it on youtube and in AI, but I couldn’t find a way that really worked

my code:

st.header("Assembly")

    st.markdown("""
        <script>
            const textArea = document.getElementById("text_area_1");

            textArea.addEventListener("keydown", function(event) {
                if (event.key === "Tab") {
                    event.preventDefault();
                    const start = textArea.selectionStart;
                    const end = textArea.selectionEnd;

                    textArea.value = textArea.value.substring(0, start) + "    " + textArea.value.substring(end);

                    textArea.selectionStart = textArea.selectionEnd = start + 4;
                }
            });
        </script>
        """, unsafe_allow_html=True)

    with stylable_container(
        key = "text_area",
        css_styles = '''
        div[data-baseweb="base-input"] > textarea {
            height: 500px;
            font-family: monospace;
        }
        '''
    ):
        codigo = st.text_area("Digite seu código")

A couple things:

  • You need to use streamlit.components.v1.html to execute JavaScript.
  • When you use components, it’s iframed, so you need to use window.parent.document... to select objects.

I modified your selectors so it works, but I’m not well-informed of the risks and best ways to accomplish this behavior, so there may be some other considerations for how best to structure the logic. :slight_smile:

import streamlit as st
from streamlit.components.v1 import html

st.header("Assembly")

html("""
   <script>
       const textArea = window.parent.document.getElementsByClassName("st-key-text_area")[0].getElementsByTagName("textarea")[0];

       textArea.addEventListener("keydown", function(event) {
           if (event.key === "Tab") {
               event.preventDefault();
               const start = textArea.selectionStart;
               const end = textArea.selectionEnd;

               textArea.value = textArea.value.substring(0, start) + "    " + textArea.value.substring(end);

               textArea.selectionStart = textArea.selectionEnd = start + 4;
           }
       });
   </script>
   """)

with st.container(key="text_area"):
   codigo = st.text_area("Digite seu código")