问题
I'm making a ShinyDashboard program and I have some troubles in finding a way to make a loop in the dashboardBody to catch MenuItems. This is a simple example of what I'm trying to fix:
library(shiny)
library(shinyjs)
library(shinydashboard)
VecNames=c("A","B","C","D","E")
ui <- dashboardPage(
dashboardHeader(title = "My Page"),
dashboardSidebar(sidebarMenuOutput("sideBar_menu_UI")),
dashboardBody(
uiOutput("body_UI"),
uiOutput("test_UI")
)
)
server <- shinyServer(function(input, output, session) {
output$sideBar_menu_UI <- renderMenu({
sidebarMenu(id = "sideBar_Menu",
menuItem("Menu 1", tabName="menu1_tab", icon = icon("calendar"),
lapply(1:length(VecNames), function(i) {
menuSubItem(VecNames[i], tabName = VecNames[i] ,icon = icon("angle-right"))
})
),
menuItem("Menu 2", tabName="menu2_tab", icon = icon("database"))
)
})
output$test_UI <- renderUI ({
A=tabItems(
tabItem(tabName = "menu1_tab", uiOutput("menu1_UI")),
# lapply(1:5, function(i){
# tabItem(tabName = VecNames[i], uiOutput(paste0("Menu",i)))
# }),
tabItem(tabName = VecNames[1], uiOutput(paste0("Menu",1))),
tabItem(tabName = VecNames[2], uiOutput(paste0("Menu",2))),
tabItem(tabName = VecNames[3], uiOutput(paste0("Menu",3))),
tabItem(tabName = VecNames[4], uiOutput(paste0("Menu",4))),
tabItem(tabName = VecNames[5], uiOutput(paste0("Menu",5))),
tabItem(tabName = "menu2_tab", uiOutput("menu2_UI"))
)
})
output$body_UI <- renderUI ({
p("Default content in body outsite any sidebar menus.")
})
output$menu1_UI <- renderUI ({
box("Menu 1 Content")
})
output$menu2_UI <- renderUI ({
box("Menu 2 Content")
})
lapply(1:5, function(i){
output[[paste0("Menu",i)]]<- renderUI({
box(paste0("Menu",i))
})
})
})
runApp(list(ui= ui, server = server))
I want something like the following code but it seems that lapply doesn't accept tabItem as a function
# lapply(1:5, function(i){
# tabItem(tabName = VecNames[i], uiOutput(paste0("Menu",i)))
# })
Any help? Thank you for your answers on advanced
回答1:
The problem in your code is, that you try to use a list of tabItem
objects as an argument for tabItems
, but this is invalid according to the documentation of tabItems
.
tabItems(...)
...
Items to put in the container. Each item should be a tabItem.
do.call
can be used to resolve this issue. Basically, do.call
operates as follows.
add <- function(x, y){x + y}
do.call(add, list(4, 3)) # same as add(4, 3)
## 7
So you basically want to use the list returned from lapply
as the second argument to do.call
while the first argument is the function to call (tabItems
).
output$test_UI <- renderUI ({
items <- c(
list(tabItem(tabName = "menu1_tab", uiOutput("menu1_UI"))),
lapply(1:5, function(i){
tabItem(tabName = VecNames[i], uiOutput(paste0("Menu",i)))
})
)
do.call(tabItems, items)
})
来源:https://stackoverflow.com/questions/46909890/how-to-make-a-function-in-a-for-loop-or-lapply-loop-in-a-tabitem-dashboard-shiny