Switching between menuSubItems in shinyDashboard

Sam picture Sam · Sep 29, 2015 · Viewed 8k times · Source

I'm trying to set up a shiny app using shinydashboard, and for the most part, having good luck. However, I'm running into a quirk with sidebar behavior that I think is avoidable, but haven't found how yet.

Below is a small example that reproduces the problem I'm having. Basically, there are two sidebarMenus - Menu One and Menu Two, each with two menuSubItems. Switching subitems within a menu item works fine. So, if I wanted to switch from subItemOne to subItemTwo, no problems. I can do that all day.

I can also switch to subItems across menus, such that jumping from subItemOne to subItemThree, that's fine. The problem lies in trying to switch back. If subItemOne is selected, and I try to go to subItemThree and back to subItemOne, I can't do it. I have to go to subItemTwo, then I can open SubItemOne.

Is there a way to correct this setup such that I could jump directly from subItemOne to subItemThree (or two and four) and back again?

library('shiny')
library('shinydashboard')
# Sidebar #############################
sidebar <- dashboardSidebar(
  width = 290,

  sidebarMenu(
    menuItem('Menu One', tabName = 'menuOne', icon = icon('line-chart'), 
        collapsible = 
            menuSubItem('Sub-Item One', tabName = 'subItemOne'),
            menuSubItem('Sub-Item Two', tabName = 'subItemTwo')
            )
  ),

  sidebarMenu(
    menuItem('Menu Two', tabName = 'menuTwo', icon = icon('users'), 
             collapsible = 
               menuSubItem('Sub-Item Three', tabName = 'subItemThree'),
             menuSubItem('Sub-Item Four', tabName = 'subItemFour')
    )
  )

)
# Body #############################
body <- dashboardBody(

  tabItems(
    tabItem(tabName = 'subItemOne',
            h2('Selected Sub-Item One')
    ),
    tabItem(tabName = 'subItemTwo',
            h2('Selected Sub-Item Two')
    ),
    tabItem(tabName = 'subItemThree',
            h2('Selected Sub-Item Three')
    ),
    tabItem(tabName = 'subItemFour',
            h2('Selected Sub-Item Four')
    )
  )
)
# UI #############################
ui <- dashboardPage(
  dashboardHeader(title = 'Test', titleWidth = 290),
  sidebar,
  body
)
# Server #############################
server <- function(input, output){

}

shinyApp(ui, server)

Answer

OsFo picture OsFo · Oct 15, 2015

The problem is that the tab items stay active and clicking on an active tab item doesn't update the UI. This can be fixed with some Javascript.

library('shiny')
library('shinydashboard')
# Sidebar #############################
sidebar <- dashboardSidebar(
  tags$head(
    tags$script(
      HTML(
        "
        $(document).ready(function(){
          // Bind classes to menu items, easiet to fill in manually
          var ids = ['subItemOne','subItemTwo','subItemThree','subItemFour'];
          for(i=0; i<ids.length; i++){
            $('a[data-value='+ids[i]+']').addClass('my_subitem_class');
          }

          // Register click handeler
          $('.my_subitem_class').on('click',function(){
            // Unactive menuSubItems
            $('.my_subitem_class').parent().removeClass('active');
          })
        })
        "
      )
    )
  ),
  width = 290,

  sidebarMenu(
    menuItem('Menu One', tabName = 'menuOne', icon = icon('line-chart'),
             collapsible = 
               menuSubItem('Sub-Item One', tabName = 'subItemOne'),
             menuSubItem('Sub-Item Two', tabName = 'subItemTwo')
    )
  ),

  sidebarMenu(
    menuItem('Menu Two', tabName = 'menuTwo', icon = icon('users'), 
             collapsible = 
               menuSubItem('Sub-Item Three', tabName = 'subItemThree'),
             menuSubItem('Sub-Item Four', tabName = 'subItemFour')
    )
  )

)
# Body #############################
body <- dashboardBody(

  tabItems(
    tabItem(tabName = 'subItemOne',
            h2('Selected Sub-Item One')
    ),
    tabItem(tabName = 'subItemTwo',
            h2('Selected Sub-Item Two')
    ),
    tabItem(tabName = 'subItemThree',
            h2('Selected Sub-Item Three')
    ),
    tabItem(tabName = 'subItemFour',
            h2('Selected Sub-Item Four')
    )
  )
)
# UI #############################
ui <- dashboardPage(
  dashboardHeader(title = 'Test', titleWidth = 290),
  sidebar,
  body
)
# Server #############################
server <- function(input, output){

}

shinyApp(ui, server)