Mark Heckmann
Mark Heckmann

Reputation: 11431

Shiny dashboard - hide menuitem in server generated sidebar UI

I have a server generated sidebar. After its creation, I want to hide its first element. The observer doing the hiding is executed, however, the menuitem is not hidden. I am trying to figure out, why it does not work. Any thoughts?

PS. The CSS selector appears to be correct, as all works when the UI is not created on the server.

library(shiny)
library(shinyjs)
library(shinydashboard)


ui <- dashboardPage(
    dashboardHeader(),
    dashboardSidebar(
      uiOutput("sidebar_ui")
    ),
    dashboardBody(
      shinyjs::useShinyjs()
    )
   )


server <- function(session, input, output) 
{ 
  rv <- reactiveValues()

  output$sidebar_ui <- renderUI({
    rv$trigger_sidebar_config <- 0
    cat("\nSidebar create")
    sidebarMenu(id = "sidebar",
                menuItem("Menu1", tabName = "tab_menu_1"),  # to be hidden
                menuItem("Menu2", tabName = "tab_menu_2") )
  })


  observeEvent(rv$trigger_sidebar_config, {
    cat("\nSidebar config")
    shinyjs::hide(selector = '[data-value="tab_menu_1"]')  # hide menuitem
  })
}

shinyApp(ui, server)

Upvotes: 0

Views: 902

Answers (1)

ismirsehregal
ismirsehregal

Reputation: 33397

Your observeEvent is executed too early because the reactive value trigger_sidebar_config is updated during the same cycle as renderUI. Accordingly shiny tries to hide an UI element which isn't existing yet (you would have to wait for the UI beeing rendered, instead of it's calculation beeing triggered, for this to work).

You can test this e.g. via delaying the execution of shinyjs::hide - it works when triggered by an actionButton (Please see my below example) or you have a look at the reactlog:

reactlog Here you can see, that the observeEvent triggered via trigger_sidebar_config finished calculating after 3ms but the sidebar wasn't ready at this time (30ms).

If you want the tab to be hidden on startup you can use hidden() in your renderUI call (see Menu3):

library(shiny)
library(shinyjs)
library(shinydashboard)


ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    uiOutput("sidebar_ui")
  ),
  dashboardBody(
    shinyjs::useShinyjs(),
    actionButton("hide", "hide tab")
  )
)


server <- function(session, input, output) 
{ 
  rv <- reactiveValues()

  output$sidebar_ui <- renderUI({
    rv$trigger_sidebar_config <- 0
    cat("\nSidebar create")
    sidebarMenu(id = "sidebar",
                menuItem("Menu1", tabName = "tab_menu_1"),  # to be hidden
                menuItem("Menu2", tabName = "tab_menu_2"),
                shinyjs::hidden(menuItem("Menu3", tabName = "tab_menu_3")))
  })


  observeEvent(input$hide, {
    cat("\nSidebar config")
    shinyjs::hide(selector = '[data-value="tab_menu_1"]')  # hide menuitem
  })
}

shinyApp(ui, server)

In this context please also see ?renderMenu().

Upvotes: 1

Related Questions