在Shiny Module中的renderUI()中使用lapply()

我试图将一段代码转换为Shiny模块,但我在lapply()中生成的renderPlot()函数似乎不起作用.我在下面创建了一个简单的例子来演示这个问题.

(注意:这里我使用的是renderText()调用,但同样的行为适用.)

app_normal.R:

library(shiny)

ui <- fixedPage(
  h2("Normal example"),
  uiOutput("test")
)

server <- function(input, output, session) {
  output$test <- renderUI({
    lapply(1:3, function(val) {
      fluidRow(column(12,renderText(paste("Line", val))))
    })
  })
}

shinyApp(ui, server)

app_module.R:

library(shiny)

myModuleUI <- function(id) {
  ns <- NS(id)
  uiOutput(ns("test"))
}

myModule <- function(input, output, session) {
  output$test <- renderUI({
    lapply(1:3, function(val) {
      fluidRow(column(12,renderText(paste("Line", val))))
    })
  })
}

ui <- fixedPage(
  h2("Module example"),
  myModuleUI("test_module")
)

server <- function(input, output, session) {
  callModule(myModule, "test_module")
}

shinyApp(ui, server)

正在创建所有div元素,但它们只是无法包含绘图/文本.如何在模块内的renderUI()/ lapply()调用中正确使用Shiny renderText()或renderPlot()函数?

最佳答案 看来我在renderUI()中直接使用renderText()和renderPlot()函数的方法在正常情况下工作正常,即不在Shiny模块中操作时. Shiny会自动调用必要的textOutput()或plotOutput()来生成HTML.在Shiny模块中执行相同操作时,如何破坏此自动链接.我怀疑这是由于在分配outputIds时引入ns()调用导致输出列表中的项目分配和引用不匹配,因为在调用outputPlot()或outputText()时手动完成.

要在Shiny模块中成功使用renderUI,您需要在renderUI()中的lapply()中单独调用textOutput()和renderText():textOutput,并在observe()中的lapply()中调用renderText().这允许我们将ns()引入到textOutput()调用的outputId的生成中.

下面我已经包含了app_normal.R和app_module.R的重构,它们展示了这两个调用的解密.

app_normal_observe.R:

library(shiny)

ui <- fixedPage(
  h2("Normal example"),
  uiOutput("test")
)

server <- function(input, output, session) {
  output$test <- renderUI({
    lapply(1:3, function(val) {
      fluidRow(column(12,textOutput(paste0("line_", val))))
    })
  })

  observe({
    lapply(1:3, function(val) {
      output[[paste0("line_", val)]] <- renderText(paste("Line", val))
    })
  })
}

shinyApp(ui, server)

app_module_observe.R:

library(shiny)

myModuleUI <- function(id) {
  ns <- NS(id)
  uiOutput(ns("test"))
}

myModule <- function(input, output, session) {
  output$test <- renderUI({
    lapply(1:3, function(val) {
      fluidRow(column(12,textOutput(session$ns(paste0("line_", val)))))
    })
  })

  observe({
    lapply(1:3, function(val) {
      output[[paste0("line_", val)]] <- renderText(paste("Line", val))
    })
  })
}

ui <- fixedPage(
  h2("Module example"),
  myModuleUI("test_module")
)

server <- function(input, output, session) {
  callModule(myModule, "test_module")
}

shinyApp(ui, server)
点赞