【问题标题】:auto-resize textAreaInput in shiny R在闪亮的 R 中自动调整 textAreaInput 的大小
【发布时间】:2025-11-24 01:35:01
【问题描述】:

我正在尝试调整 this SO answer 关于如何通过 javascript 为闪亮 R 自动调整 textarea 输入的大小。理想情况下,我想避免使用 ShinyJS 等帮助程序包。

首先我尝试了一个纯 javascript 实现,在该实现中我将 javascript 按原样加载到应用程序中(方法 1)。然后我尝试从闪亮的observeEvent触发javascript函数(方法2)。

这两种方法都不起作用。 好像我错过了什么。

方法一:

library(shiny)

jsCode1 <- "
            var observe;
            if (window.attachEvent) {
            observe = function (element, event, handler) {
            element.attachEvent('on'+event, handler);
            };
            }
            else {
            observe = function (element, event, handler) {
            element.addEventListener(event, handler, false);
            };
            }
            function init () {
            var text = document.getElementById('text');
            function resize () {
            text.style.height = 'auto';
            text.style.height = text.scrollHeight+'px';
            }
            /* 0-timeout to get the already changed text */
            function delayedResize () {
            window.setTimeout(resize, 0);
            }
            observe(text, 'change',  resize);
            observe(text, 'cut',     delayedResize);
            observe(text, 'paste',   delayedResize);
            observe(text, 'drop',    delayedResize);
            observe(text, 'keydown', delayedResize);

            text.focus();
            text.select();
            resize();
            }

            init();
            "

shinyApp(ui = 

           fluidPage(

                        tags$script(jsCode1),

                        tags$head(

                          tags$style("
                                     textarea {
                                     border: 0 none white;
                                     overflow: hidden;
                                     padding: 0;
                                     outline: none;
                                     background-color: #D0D0D0;
                                     }
                                     "
                          )

                          ),

                               shiny::tagAppendAttributes(
                                 textAreaInput(inputId = "text",
                                               label = "Enter text here",
                                               placeholder = "insert your text here",
                                               width = "100%"),
                                 style = "width: 100%;")

                        ),

         server = function(input, output, session) {

         }
                      )

方法2:

library(shiny)

jsCode2 <- "

            Shiny.addCustomMessageHandler('handler1', init);

            function init (el) {
            var text = document.getElementById(el);
            function resize () {
            text.style.height = 'auto';
            text.style.height = text.scrollHeight+'px';
            }
            /* 0-timeout to get the already changed text */
            function delayedResize () {
            window.setTimeout(resize, 0);
            }
            observe(text, 'change',  resize);
            observe(text, 'cut',     delayedResize);
            observe(text, 'paste',   delayedResize);
            observe(text, 'drop',    delayedResize);
            observe(text, 'keydown', delayedResize);

            text.focus();
            text.select();
            resize();
            }"

shinyApp(ui = 

           fluidPage(

                        tags$script(jsCode2),

                        tags$head(

                          tags$style("
                                     textarea {
                                     border: 0 none white;
                                     overflow: hidden;
                                     padding: 0;
                                     outline: none;
                                     background-color: #D0D0D0;
                                     }
                                     "
                          )

                          ),

                               shiny::tagAppendAttributes(
                                 textAreaInput(inputId = "text",
                                               label = "Enter text here",
                                               placeholder = "insert your text here",
                                               width = "100%"),
                                 style = "width: 100%;")

                        ),

         server = function(input, output, session) {

           observeEvent(input$text,{

             session$sendCustomMessage("handler1", message = "text")

           })

         }
                      )

【问题讨论】:

    标签: javascript r shiny


    【解决方案1】:

    可能是您尝试在 textinput() 添加到 DOM 之前将调整大小事件附加到后者。

    我添加了一个事件侦听器,该侦听器在附加调整大小事件之前等待 DOM 加载完毕。

    document.addEventListener('DOMContentLoaded', function(event) {...})
    

    shinyjs 会自动为您执行此操作。添加上面的事件监听器,你可以不使用shinyjs 让它工作。

    Javascript 代码:

    jsCode <- "document.addEventListener('DOMContentLoaded', function(event) {
        var observe;
        if (window.attachEvent) {
          observe = function (element, event, handler) {
            element.attachEvent('on'+event, handler);
          };
        }
        else {
          observe = function (element, event, handler) {
            element.addEventListener(event, handler, false);
          };
        }
        function init () {
          var text = document.getElementById('text');
          function resize () {
            text.style.height = 'auto';
            text.style.height = text.scrollHeight+'px';
          }
          /* 0-timeout to get the already changed text */
            function delayedResize () {
              window.setTimeout(resize, 0);
            }
          observe(text, 'change',  resize);
          observe(text, 'cut',     delayedResize);
          observe(text, 'paste',   delayedResize);
          observe(text, 'drop',    delayedResize);
          observe(text, 'keydown', delayedResize);
    
          text.focus();
          text.select();
          resize();
        };init()
      })
    "
    

    应用程序:

    library(shiny)
    
    ui <- fluidPage(
      shiny::tags$script(jsCode),
      textAreaInput(inputId = "text", label = "a", value = "b")
    )
    
    server <- function(input, output, session) {
    }
    
    shinyApp(ui, server)
    

    【讨论】:

    • 像魅力一样工作!