R shiny- How to change color of menuitem when any submenuitem is selected

Viewed 469

I have a shiny app where there are many menuitems with submenuitems. In my code, active submenuitem are highlighted with different color than the non active submenuitems. Can someone help with changing the color of the menuitem (making it same as submenuitem) when any submenuitem is active?

Please refer to screenshot below:- can we change color for "First" as well when "Chart" or "Dashboard" is selected?

enter image description here

Below is the reusable code for this:-

library(shiny)
library(shinydashboard)
library(gapminder)

tabledata<-gapminder

header <- dashboardHeader(
  title = "Test Dashboard"
)

sidebar <- dashboardSidebar(
  sidebarMenu (
    menuItem("First",startExpanded = TRUE,
             menuSubItem("Dashboard", tabName = "tab1"),
             menuSubItem("Chart", "tab2")
    ),
    menuItem("Second",startExpanded = TRUE,
             menuSubItem("Detailed_view", tabName = "tab3")
    )
  )
)

body <- dashboardBody(
  tags$head(tags$style(HTML('
                            /* main sidebar */
                            .skin-blue .main-sidebar {
                            background-color: #EBEBEB;

                            }

                            /* active selected tab in the sidebarmenu */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu .active a{
                            background-color: #E0E0E0;
                            color: #666666;
                            }

                            /* other links in the sidebarmenu */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu a{
                            background-color: #EBEBEB;
                            color: #666666;
                            }

                            /* other links in the sidebarmenu when hovered */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu a:hover{
                            background-color: #E0E0E0;
                            color: #000000;
                            }
                            '))),
  tabItems(
    tabItem(tabName = "tab1",
            box(title = "Table", width = 10, status = "warning", DT::dataTableOutput("table"))
    ),
    tabItem(tabName = "tab2",
            plotOutput("plot1")
    )
  )
)

ui <- dashboardPage(skin = "blue",header, sidebar, body)

server <- function(input, output) {
  
  output$table = DT::renderDataTable({
    DT::datatable(tabledata)
  })
  
  output$plot1<-renderPlot({
    plot(tabledata$year,tabledata$pop)
  })
  
}

shiny::shinyApp(ui, server)
1 Answers

A bit of JavaScript is your friend:

js <- HTML("
$(function() {
   $('.menu-open > .active').parentsUntil('.sidebar', 'li').children('a:first-child').addClass('has-selected-child');
   $('.menu-open > li').on('click', function() {
      let $me = $(this);
      let $menu = $me.parents('.main-sidebar');
      $menu.find('.has-selected-child').removeClass('has-selected-child');
      $me.parentsUntil('.sidebar', 'li').children('a:first-child').addClass('has-selected-child');
   })
})")

body <- dashboardBody(
  tags$head(tags$script(js)),
  tags$head(tags$style(HTML('

                            /* selected parent */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu .has-selected-child {
                            background-color: #E0E0E0;
                            color: #666666;
                            }
                            /* main sidebar */
                            .skin-blue .main-sidebar {
                            background-color: #EBEBEB;
                            }

                            /* active selected tab in the sidebarmenu */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu .active a{
                            background-color: #E0E0E0;
                            color: #666666;
                            }

                            /* other links in the sidebarmenu */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu a{
                            background-color: #EBEBEB;
                            color: #666666;
                            }

                            /* other links in the sidebarmenu when hovered */
                            .skin-blue .main-sidebar .sidebar .sidebar-menu a:hover{
                            background-color: #E0E0E0;
                            color: #000000;
                            }
                            '))),
  tabItems(
    tabItem(tabName = "tab1",
            box(title = "Table", width = 10, status = "warning", DT::dataTableOutput("table"))
    ),
    tabItem(tabName = "tab2",
            plotOutput("plot1")
    )
  )
)

Explanation

  • We assign a click event handler to each menu item, which assigns the class has-selected-child to the parent of the clicked element (and removes this class from all other elements)
  • We then define some CSS to color this element appropriately.
  • Last thing is to assign the class initially to the first element (there was no click yet).
Related