I have this first version (MWE) of my app that works well. The menuItems
and TabItems
are hard-coded. As you can see there are some menus that are inside others. :
library(shiny)
library(shinydashboard)
ui<-dashboardPage(header=dashboardHeader( title = "MyApp")
,sidebar=dashboardSidebar(uiOutput("sidebarpanel"))
,body=dashboardBody(uiOutput("body"))
,skin = "green",title = "Simple Dashboard")
server <- function(input, output) {
output$sidebarpanel <- renderMenu({
sidebarMenu(id="tabs",menuItem(text='Grandfather01',tabName = 'tabnameGrandfather01')
,menuItem(text='Grandfather02'
,menuItem(text='Father02_01'
,menuItem(text='Child02_01_01',tabName = 'tabNameChild02_01_01')
,menuItem(text='Child02_01_02',tabName = 'tabNameChild02_01_02')
)
)
,menuItem(text='Grandfather03'
,menuItem(text='Father03_01',tabName = 'tabNameFather03_01')
)
)
})
output$body <- renderUI({
tabItems(
tabItem(tabName="tabnameGrandfather01",actionButton("buttonGrandfather01","buttonGrandfather01"))
,tabItem(tabName="tabNameChild02_01_01",actionButton("buttontabNameChild02_01_01","buttontabNameChild02_01_01"))
,tabItem(tabName="tabNameChild02_01_02",actionButton("buttonChild02_01_02","buttonChild02_01_02"))
,tabItem(tabName="tabNameChild02_01_02",actionButton("buttonChild02_01_02","buttonChild02_01_02"))
,tabItem(tabName="tabnameFather02_02",actionButton("buttonFather02_02","buttonFather02_02"))
,tabItem(tabName="tabNameFather03_01",actionButton("buttonFather03_01","buttonFather03_01"))
)
})
}
# Run the application
shinyApp(ui = ui, server = server)
It makes the menus to appear in this way that is OK:
Now, my new requirement is to easily include/exclude some menus. So, I thought to use a list
to comment/uncomment some elements of that list. Since there are some menus that are inside others, I have to use a nested list
and recursive
functions.
I tried to do it in this way but I couldn't figure out:
library(shiny)
library(shinydashboard)
myList<-list()
myList[[length(myList)+1]]<-list(text="Grandfather01",tabName='tabnameGrandfather01',button="buttonGrandfather01")
myList[[length(myList)+1]]<-list(text="Grandfather02",
list(text="Father02_01"
,list(text='Child02_01_01',tabName='tabNameChild02_01_01',button="buttonChild02_01_01")
,list(text='Child02_01_01',tabName='tabNameChild02_01_01',button="buttonChild02_01_02")
)
)
myList[[length(myList)+1]]<-list(text="Grandfather03",
list(text='Father03_01',tabName='tabNameFather03_01',button="buttonFather03_01")
)
# Excluded:No need for now.
#myList[[length(myList)+1]]<-list(text="Grandfather04",tabName='tabnameGrandfather04',button="buttonGrandfather04")
#myList[[length(myList)+1]]<-list(text="Grandfather05",
# list(text='Father05_01',tabName='tabNameFather05_01',button="buttonFather05_01")
# )
funGetTabItem<-function(lst){
mylst<-list()
if(!is.null(lst$tabName)){
return(tabItem(tabName=lst$text,actionButton(lst$button,lst$button)))
}
else {
for ( i in seq_len(length(lst))){
if (is.list(lst[[i]])) mylst[[length(mylst)+1]]<-funGetTabItem(lst[[i]])
}
return(mylst)
}
}
funGetMenuItem<-function(lst){
mylst<-list()
if(!is.null(lst$tabName)){
return(menuItem(lst$text,tabName=lst$tabName))
}
else {
for ( i in seq_len(length(lst))){
if (is.list(lst[[i]])) mylst[[length(mylst)+1]]<-menuItem(lst$text,funGetMenuItem(lst[[i]]))
}
return(mylst)
}
}
ui<-dashboardPage(header=dashboardHeader( title = "MyApp")
,sidebar=dashboardSidebar(uiOutput("sidebarpanel"))
,body=dashboardBody(uiOutput("body"))
,skin = "green",title = "Simple Dashboard")
server <- function(input, output) {
output$sidebarpanel <- renderMenu({
lstMenuItem<-funGetMenuItem(myList)
sidebarMenu(id="tabs",lstMenuItem)
})
output$body <- renderUI({
lstTabItem<-funGetTabItem(myList)
do.call(tabItems, lstTabItem)
})
}
# Run the application
shinyApp(ui = ui, server = server)
This error appears, but I think it is not going to be the only one:
Warning: Error in FUN: Expected an object with class 'shiny.tag'.
102: stop
101: FUN
100: lapply
99: <Anonymous>
97: renderUI [D:\Proyectos\scibtracker\appxx/app.R#65]
96: func
83: renderFunc
82: output$body
1: runApp
I'm not sure whether I chose the worst approach for that requirement or if my attempt is OK, can you give some suggestions or help me to fix it?