在一个闪亮的模块中创建多个选项卡

Create multiple tabs within one shiny module

我正在使用 tabsetPanel,现在我想创建一个模块,向该面板添加多个选项卡。这是我的示例代码:

library(shiny)
library(tidyverse)

resultlistUI <- function(id) {
  ns <- NS(id)
  tabPanel(
    title = "Result1",
    "Some text here 2"
  )
  tabPanel(
    title = "Result2",
    "Some text here 3"
  )
}

resultlist <- function(input, output, session) {
}

ui <- fluidPage(
  tabsetPanel(
    id = "tabs",
    tabPanel(
      title = "Tab 1",
      "Some text here"
    ),
    resultlistUI(id = "resultlist1")
  )
)

server <- function(input, output, session) {
}


shinyApp(ui = ui, server = server)

我首先想知道为什么我不能简单地用逗号分隔两个选项卡。当我执行代码时,只有我的第二个选项卡 "Result2" 被添加到 tabsetPanel。我也尝试使用 tagList 但随后显示了 none 个选项卡。我做错了什么?

编辑: 添加了完整的最小可重现示例 - 仅显示主应用程序的第一个选项卡和模块的第二个选项卡。

问题可能来自函数 tabsetPanel 使用其参数的方式。 该函数需要用逗号分隔的 tabPanel。

在做你正在做的事情时,你在一个参数中提供了两个 tabPanel。

因此,您必须想出一种方法,让您可以为每个参数提供一个选项卡。通过从您的模块返回一个列表并使用函数 do.call 您可以实现这一点。

library(shiny)
library(tidyverse)

resultlistUI <- function(id) {
  ns <- NS(id)
  list(
    tabPanel(
      title = "Result1",
      "Some text here 2"
    ),
    tabPanel(
      title = "Result2",
      "Some text here 3"
    ))
}


resultlist <- function(input, output, session) {
}


ui <- fluidPage(

  do.call(tabsetPanel, 
          list(id = 'tabs', 
               tabPanel(
                 title = "Tab 1",
                 "Some text here"
               )) %>% append(resultlistUI(id = "resultlist1")))

)

server <- function(input, output, session) {
}


shinyApp(ui = ui, server = server)

此外,不确定你的模块应该做什么,但你没有在服务器内部调用 resultList,你需要在你的应用程序中包含这两个部分,否则模块将无法工作。

查看这篇文章。 https://shiny.rstudio.com/articles/modules.html

我通过在模块中定义多个 UI-functions 找到了可行的解决方案。目的是该模块将数据集作为输入并对其进行一些复杂的转换。然后我想在第一个选项卡上显示一些可视化效果,并在第二个选项卡上显示一些下载按钮。由于两个选项卡都引用相同的转换数据,我想将它们封装在同一个模块中。下面的例子对我来说很好用。我想知道这是不是不好的做法?

library(shiny)
library(tidyverse)

## module start
results_1_UI <- function(id) {
  ns <- NS(id)
  tabPanel(
    title = "Plot",
    plotOutput(ns("testplot"))
  )
}
results_2_UI <- function(id) {
  ns <- NS(id)
  tabPanel(
    title = "Export",
    downloadButton(ns("download_data"), "Download")
  )
}

results <- function(input, output, session, data) {
  ## do some complicated data transformations
  data_transformed <- data

  output$testplot <- renderPlot(
    {
      data_transformed %>%
        ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
        geom_point()
    })
  output$download_data <- downloadHandler(
    filename = function() {
      paste("data_", Sys.time(), ".csv", sep = "")
    },
    content = function(file) {
      write.csv(data_transformed, file, row.names = FALSE, quote = FALSE, na = "", fileEncoding = "latin1")
    },
    contentType = "text/csv"
  )
}
### module end

ui <- fluidPage(
  tabsetPanel(
    id = "tabs",
    tabPanel(
      title = "Tab 1",
      "Some text here"
    ),
    results_1_UI(id = "test1"),
    results_2_UI(id = "test1")
  )
)

server <- function(input, output, session) {
  callModule(
    module = results,
    id = "test1",
    data = iris
  )
}


shinyApp(ui = ui, server = server)