简体   繁体   English

RStudio Shiny 和 JavaScript 通信问题

[英]RStudio Shiny and JavaScript communication issue

I would like to make a Shiny app which makes as much HTML div object as the lenght of selected the database, but there could be a communication problem between Shiny and JavaScript.我想制作一个 Shiny 应用程序,它可以生成与所选数据库的长度一样多的 HTML div 对象,但 Shiny 和 JavaScript 之间可能存在通信问题。

I tried to use Shiny.addCustomMessageHandler but It seems to be only sends information within the function.我尝试使用 Shiny.addCustomMessageHandler 但它似乎只在函数内发送信息。 My goal is to modify the msg variable value to ncol(database() )我的目标是将 msg 变量值修改为 ncol(database() )

Here is a minimal example:这是一个最小的例子:

server.r服务器文件

library(shiny)

shinyServer(
function(input, output, session) {
   database <- reactive({
      get(input$database)
    })

   observe({
     session$sendCustomMessage(type = 'testmessage', message = ncol(database()))
   })
})

ui.r用户界面

library(shiny)

shinyUI(fluidPage(
  tags$head(tags$script(src="script.js")),

  fluidRow(
  # TITLE
  titlePanel("title"),

  # SIDEBAR
  sidebarPanel(width = 2,
      selectInput("database", "Select sample database:", choices = c("mtcars","iris","Titanic","AirPassengers"))
    )
  ),

  # MAIN-PANEL
  column(width = 8,  
    tabsetPanel(type = "pills",  
       tabPanel("view",        
           tags$div(id="target")
        )
  ))
))

script.js脚本.js

$(document).on('shiny:connected', function(event) {

          var msg;
            Shiny.addCustomMessageHandler("testmessage",
              function(message) {
                msg = message;                                      
              }
            );

          for(var i =1; i<= msg; i++){
             $('#target').append($('<div/>', { id: 'targ' + i, 'class' : 'col-md-4'}))
          }
}); 

Thanks for any suggestion!感谢您的任何建议!

UPDATE1:更新1:

When I generates plots like this:当我生成这样的图时:

$(document).ready(function() {
    Shiny.addCustomMessageHandler("testmessage",
    function(message) {
      updateTargetDiv(message);
    }
    );
});

function updateTargetDiv(msg){
      node = document.getElementById('target');
      while (node.hasChildNodes()) {
          node.removeChild(node.lastChild);
      }
      for(var i =1; i<= msg; i++){
         $('#target').append($('<div/>', { id: 'targ' + i, 'class' : 'col-md-4'}));
      }

            for(var i =1; i<= msg; i++){
                 $('#targ' + i).append($('<div/>', { id: 'plot' + i, 'class' : 'col-md-3 shiny-plot-output'}))
                 $('#targ' + i).append($('<div/>', { id: 'summary' + i, 'class' : 'col-md-1 shiny-html-output'}))
            }
}

server.r服务器文件

observe({
      for (i in 1:ncol(database())) {
        local({
            my_i = i
            output[[paste0('plot',i)]]  <- renderPlot({
              db = database()
              ggplot(data = db, 
                     aes_string(colnames(db)[my_i])) +
              geom_histogram()
            }) 

            output[[paste0('summary',i)]]  <- renderTable({
              db = database()
              mat = matrix(NA,6,2)
              mat[,1] = names(summary(db[,my_i]))
              mat[,2] = summary(db[,my_i])
              mat
            }, include.colnames=FALSE)
        })
      }
    })

I cannot se any plots.我看不到任何情节。 Why?为什么? (It works without JavaScript dynamic div script) (它在没有 JavaScript 动态 div 脚本的情况下工作)

Based on your description, I think the main problem is that you only call your JavaScript function once.根据您的描述,我认为主要问题是您只调用了一次 JavaScript 函数。 .on('shiny:connected' ... is only called once at the start. .on('shiny:connected' ...在开始时只调用一次。

Another issue is that you are only ever adding to the target div , so it will keep growing unless you clear its children div elements.另一个问题是您只会添加到目标div ,因此除非您清除其子div元素,否则它将继续增长。

I think the code below will suit your needs.我认为下面的代码将满足您的需求。 It creates the CustomMessageHandler once and will call the updateTargetDiv any time a new value is passed in. It also clears the children div elements from target before creating the new ones.它创建CustomMessageHandler一次,将调用updateTargetDiv一个新值传入任何时候,它还会清除孩子div从目标元素创建新的之前。

$(document).ready(function() {
  Shiny.addCustomMessageHandler("testmessage",
    function(message) {
      updateTargetDiv(message);
    }
  );
});

function updateTargetDiv(msg){
      node = document.getElementById('target');
      while (node.hasChildNodes()) {
          node.removeChild(node.lastChild);
      }
      for(var i =1; i<= msg; i++){
         $('#target').append($('<div/>', { id: 'targ' + i, 'class' : 'col-md-4'}));
      }
}

Visual:视觉的: 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM