在 DT 回调的模块内部使用 Shiny.setInputValue

use Shiny.setInputValue inside module from DT callback

我在一个更大的应用程序中遇到问题,我将其缩小到这个 repex

我在模块中有一个 DT table。我需要通过单击从 table 的行中获取数据。为此,我使用 DT::renderDataTable

中的回调参数

在模块外,没问题。在模块内部,我无法取回点击事件数据。 在资源管理器控制台中,它说该值不存在,因此无法记录它。

library(shiny)
library(DT)

tableUI <- function(id){
  ns <- NS(id)
  tagList(
    DT::dataTableOutput(ns("mytable"))
    textOutput(ns("mytext"))
  )
}

tableServer <- function(id){
  moduleServer(id, function(input, output, session){
    output$mytable = DT::renderDataTable({
      mtcars
    },
    callback = JS('table.on("click.dt", "tr",
                      function() {
                      data = table.rows(this).data().toArray();
                      Shiny.setInputValue("mytext1", data, {priority: "event"});
                      console.log(mytext1);
                      });')
    )
    
    observeEvent(req(input$mytext1), {
      output$mytext <- renderText(input$mytext1)
    })
  })
}
ui <- basicPage(
  tableUI("table1")
)

server <- function(input, output) {
  tableServer("table1")
}

shinyApp(ui, server)

我尝试将 ns id 添加到 setInputValue id,例如“mytable-mytext1”,但这给了我一个闪亮的错误,应用程序甚至没有启动:

Warning: Error in eval: object 'mytext1' not found
  [No stack trace available]

您需要使用 Shiny.setInputValue() 包含模块命名空间。你 提到尝试使用 "mytable-mytext1" 但那是使用 table ID,而不是 构建命名空间的模块 ID。相反,你会想要 "table1-mytext1"。 更好的构建方法是使用 sessions$ns()(见下文)。

此外,对于您展示的示例,您不需要使用自定义 callback 第一名。您可以改用内置的 DT 为最后单击的行创建的输入。

library(shiny)
library(DT)

tableUI <- function(id) {
  ns <- NS(id)
  tagList(
    DT::dataTableOutput(ns("mytable")),
    textOutput(ns("mytext1")),
    textOutput(ns("mytext2")),
  )
}

tableServer <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$mytable <- DT::renderDataTable(
      mtcars,
      callback = JS(sprintf(
      'table.on("click.dt", "tr", function() {
        data = table.rows(this).data().toArray();
        Shiny.setInputValue("%s", data);
      });', session$ns("mytext1")))
    )
    
    output$mytext1 <- renderText(req(input$mytext1))
    output$mytext2 <- renderText({
      row <- mtcars[req(input$mytable_row_last_clicked), ]
      # Need to append rowname to match the JavaScript result
      c(rownames(row), as.character(row))
    })
  })
}

ui <- basicPage(
  tableUI("table1")
)

server <- function(input, output) {
  tableServer("table1")
}

shinyApp(ui, server)