0
votes

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".

1

1 Answers

-1
votes
observeEvent(input$sidebarItemExpanded == 'DDdashboard',{

print("DDdashboard_selected")

  })