如何在 Shiny 应用程序中正确使用 MutationObserve

问题描述

我正在尝试使用 Shiny 中的 javascript mutationObserver 观察 css 的变化。我使用 rhandsontable 是因为我们可以更改应用程序中表格元素的宽度,并且我正在尝试通过 mutationObserver 获取此更改。

javascript 似乎不起作用。我不确定为什么。控制台没有记录任何内容,没有警报消息,并且 Shiny 不会注册由 javascript 设置的变量。

MutationObserver 代码

jsCode <- "
    const observer = new MutationObserver(
      # this function runs when something is observed.
      function(mutations){
        console.log('activated')
        var i;
        var text;
        var widthArray = [];
        text = ''
        for (i = 0; i < document.getElementsByClassName('htCore')[0].getElementsByTagName('col').length; i++) {
          text += document.getElementsByClassName('htCore')[0].getElementsByTagName('col')[i].style.width + '<br>';
          widthArray.push(document.getElementsByClassName('htCore')[0].getElementsByTagName('col')[i].style.width);
        }
        alert(text)
        Shiny.setInputValue('colWidth',widthArray);
      }
    )
    const cols = document.getElementsByClassName('htCore')[0].getElementsByTagName('col')
    observer.observe(cols,{
      attributes: true # observe when attributes of ul.bears change (width,height)
    })
"

闪亮代码

library(shiny)
library(rhandsontable)

ui <- fluidPage(
  tags$head(tags$script(HTML(jsCode))),rhandsontable::rHandsontableOutput("dataTable")
)
server <- function(input,output,session) {
    df = data.frame(
        company = c('a','b','c','d'),bond = c(0.2,1,0.3,0),equity = c(0.7,0.5,1),cash = c(0.1,0.2,stringsAsFactors = FALSE
    )
  output$dataTable <- renderRHandsontable({
      rhandsontable(df,manualColumnResize = TRUE,manualRowResize = TRUE)
    })
  observeEvent(input$colWidth,{
    print(input$colWidth)
  })
}
shinyApp(ui,server)


解决方法

这有效:

jsCode <- "
$(document).on('shiny:connected',function(){
  setTimeout(function(){
    const observer = new MutationObserver(
      function(mutations){
        console.log('activated')
        var i;
        var text;
        var widthArray = [];
        text = ''
        for (i = 0; i < document.getElementsByClassName('htCore')[0].getElementsByTagName('col').length; i++) {
          text += document.getElementsByClassName('htCore')[0].getElementsByTagName('col')[i].style.width + '<br>';
          widthArray.push(document.getElementsByClassName('htCore')[0].getElementsByTagName('col')[i].style.width);
        }
        alert(text)
        Shiny.setInputValue('colWidth',widthArray);
      }
    )
    const cols = document.getElementsByClassName('htCore')[0].getElementsByTagName('colgroup')[0]
    observer.observe(cols,{
      attributes: true,subtree: true 
    });
  },500);
});
"