Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wkdavis opened this issue Jun 13, 2019 · 8 comments

Comments

@wkdavis
Copy link

@wkdavis wkdavis commented Jun 13, 2019

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 */
@kevin041811
Copy link

@kevin041811 kevin041811 commented Sep 15, 2019

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

uiOutput("body2")

@wkdavis
Copy link
Author

@wkdavis wkdavis commented Sep 16, 2019

@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.

@homer3018
Copy link

@homer3018 homer3018 commented Jan 12, 2020

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

@homer3018
Copy link

@homer3018 homer3018 commented Jun 25, 2020

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 :)

@kaijagahm
Copy link

@kaijagahm kaijagahm commented Sep 29, 2020

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!

@homer3018
Copy link

@homer3018 homer3018 commented Sep 29, 2020

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.

@kaijagahm
Copy link

@kaijagahm kaijagahm commented Sep 29, 2020

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)

@ismirsehregal
Copy link

@ismirsehregal ismirsehregal commented Oct 1, 2020

I answered the above here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants