在 Shiny App 中有条件地显示单个或多个表

Conditionally display single or multiple tables in Shiny App

我正在构建一个闪亮的应用程序,用户 select 从单选按钮菜单中获取报告,然后 table 显示在页面上。我想为用户添加一个选项来同时查看所有报告。我从这个线程 https://gist.github.com/wch/5436415/ 中找到了接近我想要的东西,但我似乎无法正确实现它。基本上,我认为我要做的是:

  1. 在 UI 中调用 uiOutput() 以响应更新用户界面。如果用户 select 按下“全部”按钮,我将需要多次调用 htmlOutput(),但如果只使用 select 一份报告,则只需要调用 htmlOutput() 一次。作为记录,我正在使用 kable() 函数创建我的 tables,这就是为什么我调用 htmlOutput() 而不是 tableOutput().

  2. 在服务器函数中,我需要调用 renderUI(),它提供了有关将有多少次 htmlOutput() 调用以及每个调用中包含哪些报告的说明打电话。

  3. 创建一个循环,然后调用 renderText,然后发送 html 代码供 htmlOutput 函数解释。

我可以走大部分路。我可以让 Shiny 具有反应性 tables,并输出单独的报告,但我正在努力让循环范围反应性更新,以便我在测试应用程序中看到所有三个 tables。这是我拥有的:

library(shiny)
library(shinydashboard)
library(knitr)
library(kableExtra)

data("cars")
data("iris")
data("airquality")

UI<-dashboardPage(
  dashboardHeader(),
  dashboardSidebar(sidebarMenu(
    menuItem("Options", radioButtons(inputId = "Tables", label="test", choices= c("cars", "iris", "airquality", "all"))
  ) )),
  dashboardBody(
    uiOutput(outputId = "TABLE"),
    textOutput("N")
  )  
  )

server<-function(input, output){
 
  TBL<-list("cars", "iris", "airquality")
  T1<-knitr::kable(head(cars))
  T2<-knitr::kable(head(iris))
  T3<-knitr::kable(head(airquality))
  tmp<-list(cars=T1, iris=T2, airquality=T3)
  TABLES<-reactive({
   ifelse(input$Tables=="all", tmp, tmp[input$Tables])
    })
  val<-reactive({
    tmp<-TABLES()
    length(tmp)})
  n<-isolate(val())
   output$TABLE<-renderUI({
    req(input$Tables)
      TAB<-TABLES()
      TBL<-names(TAB)
        tbls<-lapply(1:length(TBL), function(i){
          tblnm<-paste("tbl", i, sep="_")
          htmlOutput(tblnm)})
        do.call(tagList, tbls)
      })#Close Render UI
  for(i in 1:n){
  local({
    j<-i
    tblnm<-paste("tbl", j, sep="_")
   output[[tblnm]]<-renderText(kables(TABLES()))
    })
  }
  output$N<-renderText(n)
}#Close Server

shinyApp(ui = UI, server = server)

这是我认为我出错的地方:

我为 n 的值包含了一个 textOutput(),尽管有 reactive() 调用来获取 TABLES 的长度,当我 isolate() 我仍然得到即使我 select“全部”报告按钮时 1 的值,它应该给我 3。我是否误解了 isolate() 的工作原理?是否有另一种方法可以从可以在 *Output()reactive() 函数之外使用的 reactive() 函数中获取值?任何指导将不胜感激。非常感谢。

我认为你的 server 功能复杂得没必要。

render 函数本身是反应性上下文,因此无需将仅存在于这些上下文中的变量定义为特定反应性。

server<-function(input, output){
  TBL<-list("cars", "iris", "airquality")
  T1<-knitr::kable(head(cars))
  T2<-knitr::kable(head(iris))
  T3<-knitr::kable(head(airquality))
  tmp<-list(cars=T1, iris=T2, airquality=T3)
  output$TABLE<-renderUI({
    if(input$Tables=="all"){ind <- names(tmp)}else{ind <- input$Tables}
    lapply(tmp, HTML)[ind]
    })
  output$N <- renderText({
    if(input$Tables=="all"){ind <- names(tmp)}else{ind <- input$Tables}
    length(ind)
  })
}