shinydashboard wrong menuItem selected after adding menuSubItem

I'm having trouble controlling which menuItem is selected when my shinydashboard app loads.

The documentation says that if no menuItems have "selected = TRUE", then the first one will be selected by default. Otherwise, whichever one has "selected = TRUE" will be selected.

I have the following minimal UI:

library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
source("dashboardFunctions.R")

ui <- dashboardPagePlus(
  useShinyjs(),
  
  ## Define dashboard header: title, icon for right sidebar, etc.
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "sliders"
  ),
  
  ## Define left sidebar and menu options
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "leftSidebar",
      menuItem("Map view", tabName = "mapView", icon = icon("map"), selected = TRUE
               ),
      menuItem("Social variables", tabName = "socialVariables", icon = icon("people-fill"))
    )
  ),
  
  ## Define dashboard body (maps/graphs)
  body = dashboardBody(
    shinyDashboardThemes(theme = "grey_dark"
    ),
    tabItems(tabItem(tabName = "map", p("[Insert map here]")),
             tabItem(tabName = "socialCharts", p("[Insert charts here]"))
    )
  )
)

server <- function(input, output) {

}

shinyApp(ui = ui, server = server)

This works as expected: the "Map view" tab (which is both the first tab AND the one that has "selected = TRUE" ) is selected by default.

However, when I add a menuSubItem under the "Map view" tab, without changing anything else, that tab ceases to be selected by default. Now, even though I still have "selected = TRUE" for the map view tab, the "Social variables" tab is selected by default instead. Like this:

library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
source("dashboardFunctions.R")

ui <- dashboardPagePlus(
  useShinyjs(),
  
  ## Define dashboard header: title, icon for right sidebar, etc.
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "sliders"
  ),
  
  ## Define left sidebar and menu options
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "leftSidebar",
      menuItem("Map view", tabName = "mapView", icon = icon("map"), selected = TRUE,
               # add a menuSubItem
               menuSubItem(icon = NULL,
                           selectInput("survey", "Survey",
                                       choices = c("5", "5b", "6", "6b", "7", "8", "9", "11", "12"),
                                       selected = "11",
                                       multiple = FALSE))
               ),
      menuItem("Social variables", tabName = "socialVariables", icon = icon("gears"))
    )
  ),
  
  ## Define dashboard body (maps/graphs)
  body = dashboardBody(
    shinyDashboardThemes(theme = "grey_dark"
    ),
    tabItems(tabItem(tabName = "map", p("[Insert map here]")),
             tabItem(tabName = "socialCharts", p("[Insert charts here]"))
    )
  )
)

server <- function(input, output) {

}

shinyApp(ui = ui, server = server)

I need to have control over which tab starts selected, or at least to have "Map view" start selected, no matter how many subitems it has. I think this should work, based on the documentation--I can't figure out what I'm doing wrong--can anyone help?

Edit: I think there has been some discussion of this problem on the GH for shinydashboard, but I'm not clear on whether there is a fix yet. I posted a link to this topic there.
Thank you!

Digging down a little bit on this: it looks like not only does the mapView menu item fail to initialize as selected, but clicking on it also doesn't select it. Clicking on it opens the menuItem to show the options underneath, but that tab is not actually treated as "selected". Here is a minimal example that demonstrates which tab is selected by printing a message to the console.

library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
source("dashboardFunctions.R")

ui <- dashboardPagePlus(
  useShinyjs(),
  
  ## Define dashboard header: title, icon for right sidebar, etc.
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "sliders"
  ),
  
  ## Define left sidebar and menu options
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "leftSidebar",
      menuItem("Map view", tabName = "mapView", icon = icon("map"), selected = TRUE,
               # add a menuSubItem
               menuSubItem(icon = NULL,
                           selectInput("survey", "Survey",
                                       choices = c("5", "5b", "6", "6b", "7", "8", "9", "11", "12"),
                                       selected = "11",
                                       multiple = FALSE))
      ),
      menuItem("Social variables", tabName = "socialVariables", icon = icon("gears"))
    )
  ),
  
  ## Define dashboard body (maps/graphs)
  body = dashboardBody(
    shinyDashboardThemes(theme = "grey_dark"
    ),
    tabItems(tabItem(tabName = "map", p("[Insert map here]")),
             tabItem(tabName = "socialCharts", p("[Insert charts here]"))
    )
  )
)

server <- function(input, output) {
  observe({
    if(req(input$leftSidebar) == "mapView"){
      message("Map view has been selected.")
    }else if(req(input$leftSidebar) == "socialVariables"){
      message("Social variables view has been selected.")
    }
  })
  
}

shinyApp(ui = ui, server = server)

That's the same code as above, but with an observer added to print a message to the console depending on which tab is selected. Note that if you comment out/remove the menuSubItem, then the tab switching works fine:

library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
source("dashboardFunctions.R")

ui <- dashboardPagePlus(
  useShinyjs(),
  
  ## Define dashboard header: title, icon for right sidebar, etc.
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "sliders"
  ),
  
  ## Define left sidebar and menu options
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "leftSidebar",
      menuItem("Map view", tabName = "mapView", icon = icon("map"), selected = TRUE#,
               # add a menuSubItem
               # menuSubItem(icon = NULL,
               #             selectInput("survey", "Survey",
               #                         choices = c("5", "5b", "6", "6b", "7", "8", "9", "11", "12"),
               #                         selected = "11",
               #                         multiple = FALSE))
      ),
      menuItem("Social variables", tabName = "socialVariables", icon = icon("gears"))
    )
  ),
  
  ## Define dashboard body (maps/graphs)
  body = dashboardBody(
    shinyDashboardThemes(theme = "grey_dark"
    ),
    tabItems(tabItem(tabName = "map", p("[Insert map here]")),
             tabItem(tabName = "socialCharts", p("[Insert charts here]"))
    )
  )
)

server <- function(input, output) {
  observe({
    if(req(input$leftSidebar) == "mapView"){
      message("Map view has been selected.")
    }else if(req(input$leftSidebar) == "socialVariables"){
      message("Social variables view has been selected.")
    }
  })
  
}

shinyApp(ui = ui, server = server)

The behaviour you are describing is by design. You need to distinguish between childless and childfull menuItems.

Once you add any child elements into the menuItem it ignores the tabName and can't be selected anymore - only it's child elements can be selected (if they are childless menuItems).

However, childfull menuItems can be expanded. You can check this via input$sidebarItemExpanded. Please see the following:

library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
# source("dashboardFunctions.R")

ui <- dashboardPagePlus(
  useShinyjs(),
  
  ## Define dashboard header: title, icon for right sidebar, etc.
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "sliders"
  ),
  
  ## Define left sidebar and menu options
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "leftSidebar",
      menuItem("Map view", tabName = "mapView", icon = icon("map"), selected = TRUE,
               selectInput("survey", "Survey",
                           choices = c("5", "5b", "6", "6b", "7", "8", "9", "11", "12"),
                           selected = "11",
                           multiple = FALSE)),
      menuItem("Social variables", tabName = "socialVariables", icon = icon("gears"))
    )
  ),
  
  ## Define dashboard body (maps/graphs)
  body = dashboardBody(
    shinyDashboardThemes(theme = "grey_dark"
    ),
    tabItems(tabItem(tabName = "map", p("[Insert map here]")),
             tabItem(tabName = "socialCharts", p("[Insert charts here]"))
    )
  )
)

server <- function(input, output) {
  
  observeEvent(input$sidebarItemExpanded, {
    message("childfull sidebarItem expanded: ", input$sidebarItemExpanded)
  })
  
  observeEvent(input$leftSidebar, {
    message("childless sidebarItem selected:", input$leftSidebar)
  })
  
}

shinyApp(ui = ui, server = server)

Here you can find a related answer.

1 Like

Thank you! That makes sense. I hadn't thought to look at the childless/childfull distinction because it didn't occur to me that it would be relevant, but now that you point me there I can see that the documentation does indeed describe why my problem is happening.

I appreciate the response :slight_smile: I should be able to work with this.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.