shinydashboard icon indicating copy to clipboard operation
shinydashboard copied to clipboard

Active tab fails to display on init when menu and tabs are dynamically generated

Open wkdavis opened this issue 6 years ago • 11 comments

This is a similar case to #71, but when the body of the dashboard is also dynamically generated the app fails to display the content of the first tab, even when selected = TRUE.

library(shiny)
library(shinydashboard)
ui <- dashboardPage(
  dashboardHeader(title = "Dynamic sidebar"),
  dashboardSidebar(
    sidebarMenu(id="tabs",
                sidebarMenuOutput("menu")
    )
  ),
  dashboardBody(
    uiOutput("body")
  )
)
server <- function(input, output,session) {
  
  output$menu <- renderMenu({
    sidebarMenu(
      menuItem("Menu item1", tabName="m1", icon = icon("calendar"),selected = TRUE),
      menuItem("Menu item2", tabName="m2", icon = icon("database"))
    )
  })

  output$body <- renderUI({
    tabItems(
      tabItem(tabName = "m1", p("Menu content 1") ),
      tabItem(tabName = "m2", p("Menu content 2") )
    )
  })
}
shinyApp(ui, server)

Session info:

> sessionInfo()
R version 3.6.0 (2019-04-26)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] shinydashboard_0.7.1 shiny_1.3.2         

loaded via a namespace (and not attached):
 [1] compiler_3.6.0   magrittr_1.5     R6_2.4.0         rsconnect_0.8.13 promises_1.0.1   later_0.8.0      htmltools_0.3.6  tools_3.6.0     
 [9] Rcpp_1.0.1       jsonlite_1.6     digest_0.6.18    xtable_1.8-4     httpuv_1.5.1     mime_0.6         rlang_0.3.4     

I dug into the HTML and it looks like it recognizes that the tab should be active, based on the class of the item in the sidebar menu (<li class="active">).

<ul class="sidebar-menu">
  <ul id="menu" class="shinydashboard-menu-output shiny-bound-output sidebar-menu">
    <li class="active">
      <a href="#shiny-tab-m1" data-toggle="tab" data-value="m1" data-start-selected="1" aria-expanded="true">
        <i class="fa fa-calendar"></i>
        <span>Menu item1</span>
      </a>
    </li>
    <li>
      <a href="#shiny-tab-m2" data-toggle="tab" data-value="m2">
        <i class="fa fa-database"></i>
        <span>Menu item2</span>
      </a>
    </li>
  </ul>
  <div id="tabs" class="sidebarMenuSelectedTabItem shiny-bound-input" data-value="m1"></div>
</ul>

But when I inspect the actual panel:

<div role="tabpanel" class="tab-pane" id="shiny-tab-m1">
    <p>Menu content 1</p>
</div>

I find that it has class "tab-pane" when I think the class should be "active" based on the css (this is line 4137-4142 from bootstrap.css):

.tab-content > .tab-pane {
  display: none;
}
.tab-content > .active {
  display: block;
}

from the following version of bootstrap:

/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */

wkdavis avatar Jun 13 '19 14:06 wkdavis

Interestingly if you change the outputID in ui and the output$body to text other than "body", it works. not sure why.

uiOutput("body2")

kevin041811 avatar Sep 15 '19 15:09 kevin041811

@kevin041811 That's an interesting observation. It made me think that it has something to do with the fact that "body" is also an HTML tag, so I tried a few other examples.

  • div and div2 did not work, but divv did work.
  • span, span2, and spann all did not work.
  • li worked.
  • thead and tbody did not work.
  • p and pp did not work, but p1p did work.

I'm thinking there is some fuzzy-matching logic going on somewhere that is looking for HTML tags or something like HTML tags, but I'm not sure. For instance, I don't know why body2 works but div2 does not.

wkdavis avatar Sep 16 '19 11:09 wkdavis

This looks very similar to what I've reported earlier today (#335), might be a duplicate.

homer3018 avatar Jan 12 '20 18:01 homer3018

Hello, I'm not too sure how I would translate this fix (rename body into anything different in uiOutput(body), since I already use something different (uiOutput(TABUI) which is hosting all my tabItems). Have you got by any chance to the bottom of this ? I'm still stuck with this issue which I describe also in #335 .

Thanks ahead of time for your help :)

homer3018 avatar Jun 25 '20 09:06 homer3018

I'm having a similar problem, except my UI isn't dynamically generated--but even when I add a static UI component as a menuSubitem or just by itself under one of the menuItems, the selected tab does not display on init. I posted about this issue here on RStudio community, along with a reproducible UI example. Is there a fix for this yet?

Thank you!

kaijagahm avatar Sep 29 '20 14:09 kaijagahm

Have a look at #71, basically adding

isolate({updateTabItems(session, "sidebarmenu_id", "init_tabname")})

should do the trick with sidebarmenu_id being the id of my sidebarmenu, and init_tabname the tabName of the tab I should get upon firing the app.

homer3018 avatar Sep 29 '20 20:09 homer3018

Thank you so much for the response @homer3018! You're right that this fix works really well to get the menuItem to display initially (which is awesome). However, for some reason the menuItem still doesn't read as "selected" from the server's point of view, which means that when I write other code that depends on input$sidebarmenu_id being equal to init_tabname (i.e. code that depends on which menuItem is selected), that code won't work. Here is an example, where I've just added a bit in the server to print a message to the console when each menuItem is selected. You'll see that even while the first tab, "mapView", does now open on init, no matter how much I click between the two tabs you will never see the message "Map view has been selected" in the console, and on init the "Social variables view has been selected" message displays even though the map view tab shows up:

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, startExpanded = TRUE,
               # add a menuSubItem
               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(session, 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.")
    }
  })
  isolate({updateTabItems(session, "leftSidebar", "mapView")})
  
}

shinyApp(ui = ui, server = server)

kaijagahm avatar Sep 29 '20 21:09 kaijagahm

I answered the above here.

ismirsehregal avatar Oct 01 '20 13:10 ismirsehregal

@kaijagahm i have the same problem... when i run the app, the first tab (or menu item) is selected, but the content do not load in the body... did you find the solution ?

Franco1605 avatar Mar 06 '23 18:03 Franco1605

Honestly, it was so long ago that I barely remember. I think I used the solution described in the post linked right above your comment: https://community.rstudio.com/t/shinydashboard-wrong-menuitem-selected-after-adding-menusubitem/82561/3?u=ismirsehregal. Did you already try that?

kaijagahm avatar Mar 06 '23 20:03 kaijagahm