My aim is to build menu which content is dynamically generated and user sees only menuItems/menuSubItems starting from the top to the selected one ("next" button will be used to reach next not yet displayed menuItems/menuSubItems; in case of selection of any available menuItems/menuSubItems menu should be regenerated so the last available menuItems/menuSubItems is selected one). So I will have to play with selected and startExpanded arguments, but this is not the part of this question.
The issue I faced is mutual connection of renderMenu
and observeEvent
(that checks selected menuItem/menuSubItem). Here is the code:
library(shiny)
library(shinydashboard)
menu_generator <- function(selected = NULL, expanded = NULL){
print("menu_generator")
output <- sidebarMenu(
menuItem("Charts1", icon = icon("bar-chart-o"),
menuSubItem("AAdashboard", tabName = "AAdashboard"),
menuSubItem("BBdashboard", tabName = "BBdashboard")
),
menuItem("Charts2", icon = icon("bar-chart-o"),
menuSubItem("DDdashboard", tabName = "DDdashboard"),
menuSubItem("EWidgets", tabName = "EWidgets")
)
)
return(output)
}
ui <- dashboardPage(
dashboardHeader(title = "Test"),
dashboardSidebar(sidebarMenu(
sidebarMenuOutput("menu_output")
)),
dashboardBody(
tabItems(
tabItem(tabName = "AAdashboard",
h2("ADashboard tab content")
),
tabItem(tabName = "BBdashboard",
h2("BWidgets tab content")
),
tabItem(tabName = "DDdashboard",
h2("DWidgets tab content")
),
tabItem(tabName = "EWidgets",
h2("EWidgets tab content")
)
))
)
server <- function(input, output) {
output$menu_output <- renderMenu({
print("output$menu_output")
sidebarMenu(menu_generator(),
id = "my_menu")
})
observeEvent(input$my_menu, {
print("observer")
print(input$my_menu)
print(input$sidebarItemExpanded)
output$menu_output <- renderMenu({
sidebarMenu(menu_generator(),
id = "my_menu")
})
})
}
shinyApp(ui, server)
Scenario: expand Charts2 then click "DDdashboard".
In the console:
[1] "observer"
[1] "DDdashboard"
[1] "Charts2"
[1] "menu_generator"
[1] "observer"
[1] "AAdashboard"
NULL
[1] "menu_generator"
"observer" is called twice (as consequence "menu_generator" also), so this creates unexpected behaviour. My understanding is that reason of that is nature of renderMenu
. The question is - how to prevent Shiny from calling "observer" in this case twice? Also notice that in the second call input$my_menu
= "AAdashboard".