在 Shiny App 中有条件地显示单个或多个表
Conditionally display single or multiple tables in Shiny App
我正在构建一个闪亮的应用程序,用户 select 从单选按钮菜单中获取报告,然后 table 显示在页面上。我想为用户添加一个选项来同时查看所有报告。我从这个线程 https://gist.github.com/wch/5436415/ 中找到了接近我想要的东西,但我似乎无法正确实现它。基本上,我认为我要做的是:
在 UI 中调用 uiOutput()
以响应更新用户界面。如果用户 select 按下“全部”按钮,我将需要多次调用 htmlOutput()
,但如果只使用 select 一份报告,则只需要调用 htmlOutput()
一次。作为记录,我正在使用 kable()
函数创建我的 tables,这就是为什么我调用 htmlOutput()
而不是 tableOutput()
.
在服务器函数中,我需要调用 renderUI()
,它提供了有关将有多少次 htmlOutput()
调用以及每个调用中包含哪些报告的说明打电话。
创建一个循环,然后调用 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)
})
}
我正在构建一个闪亮的应用程序,用户 select 从单选按钮菜单中获取报告,然后 table 显示在页面上。我想为用户添加一个选项来同时查看所有报告。我从这个线程 https://gist.github.com/wch/5436415/ 中找到了接近我想要的东西,但我似乎无法正确实现它。基本上,我认为我要做的是:
在 UI 中调用
uiOutput()
以响应更新用户界面。如果用户 select 按下“全部”按钮,我将需要多次调用htmlOutput()
,但如果只使用 select 一份报告,则只需要调用htmlOutput()
一次。作为记录,我正在使用kable()
函数创建我的 tables,这就是为什么我调用htmlOutput()
而不是tableOutput()
.在服务器函数中,我需要调用
renderUI()
,它提供了有关将有多少次htmlOutput()
调用以及每个调用中包含哪些报告的说明打电话。创建一个循环,然后调用 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)
})
}