Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

activate/deactivate tab in the rightsidebar of a shinydashboardplus at click on left sidebar menu item

I'm building a Shiny app using the great ShinyDashoardPlus package (styled with a theme from the Dashboardthemes package) that has three tabItems holding the contents for the three sections of the app (section A, section B, and section C), accessible through the sidebarMenu in the left dashboardSidebar, and a right sidebar with two tabs (implemented as rightSidebarTabContent with the following ids: T_A and T_B) holding controls to explore further the contents of sections A and B respectively.

Since the rightSidebarTabContent T_A is only relevant for section A, and rightSidebarTabContent T_B is only relevant for section B, I would like that (1) the user's click on the left sidebar menu items A or B could activate the corresponding tab in the right sidebar. Moreover, since none of the rightSidebarTabContents is relevant in section C, I'd also like that (2) the user's click on the on the left sidebar menu item C could close the rightsidebar, if it is open.

I've found a possible hint on how to solve my problems (Automatic rightSidebar popup when menuItem is clicked in shinydashboardPlus), and I was indeed able to partially solve my first problem adding/removing some CSS class via shinyjs to activate a part of the different tabs in the rightSidebar at click on the menuItems.

As I said, this solution partially works for my first issue, although only the rightSidebarTabContent lower part is activated/deactivated in this way, but not the tab header with the icons for navigating between them. Moreover, possibly due to extra CSS classes added when I apply the shinydashboard theme "dark", I'm not able to toggle the closing of the rightSidebar at click on section C menu item (issue # 2).

To summarize:

  1. Right sidebar item T_A should expand when left sidebar item section A is selected. Likewise for T_A and section B.
  2. The right sidebar should collapse when section C is selected on the left sidebar

Can anyone please help with this? Thanks in advance for any help!

library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)

ui <- dashboardPagePlus(
  useShinyjs(),
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "info-circle"
  ),
  sidebar = dashboardSidebar(
    sidebarMenu(
      menuItem("Section A", tabName = "Section_A", icon = icon("map")),
      menuItem("Section B", tabName = "Section_B", icon = icon("chart-line")),
      menuItem("Section C", tabName = "Section_C", icon = icon( "gears")),
      id = "nav"
    )
  ),
  body = dashboardBody(
    shinyDashboardThemes(
      theme = "grey_dark"
    ),
    tabItems(
      tabItem(
        tabName = "Section_A",
        p("Some content for section A")),
      tabItem(
        tabName = "Section_B",
        p("Some content for section B")),
      tabItem(
        tabName = "Section_C",
        p("Some content for section C"))
      )
  ),
  rightsidebar = rightSidebar(
    background = "dark",
    rightSidebarTabContent(
      id = "T_A",
      title = "Tab for section A",
      icon = "desktop",
      active = TRUE,
      p("Some content frelevant for section A"),
      sliderInput(
        "obs",
        "Number of observations:",
        min = 0, max = 1000, value = 500
      )
    ),
    rightSidebarTabContent(
      id = "T_B",
      title = "Tab for section B",
      p("Some content frelevant for section B"),
      textInput("caption", "Caption", "Data Summary")
    )
  ),
  title = "Right Sidebar"
)


server <- function(input, output) {
  observe({
    if (req(input$nav) == "Section_A"){
      message("Section A has been selected")
      shinyjs::removeClass(id = "control-sidebar-T_A-tab", class = "tab-pane")
      shinyjs::removeClass(id = "control-sidebar-T_B-tab", class = "tab-pane active")
      shinyjs::addClass(id = "control-sidebar-T_A-tab", class = "tab-pane active")
      shinyjs::addClass(id = "control-sidebar-T_B-tab", class = "tab-pane")
    }
    if (req(input$nav) == "Section_B"){
      message("Section B has been selected")
      shinyjs::removeClass(id = "control-sidebar-T_B-tab", class = "tab-pane")
      shinyjs::removeClass(id = "control-sidebar-T_A-tab", class = "tab-pane active")
      shinyjs::addClass(id = "control-sidebar-T_B-tab", class = "tab-pane active")
      shinyjs::addClass(id = "control-sidebar-T_A-tab", class = "tab-pane")
    }
    if (req(input$nav) == "Section_C"){
      message("Section C has been selected")
      shinyjs::removeClass(selector = "aside.control-sidebar-open aside.control-sidebar-dark", class = "control-sidebar-open aside.control-sidebar-dark-open")
      shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar")
    }
  })
}


shinyApp(ui = ui, server = server)
like image 620
Stefano Guidi Avatar asked Mar 03 '23 09:03

Stefano Guidi


2 Answers

You can render your right sidebar items reactively through renderUI instead of modifying the CSS. Inside rightSidebar we can place a single uiOutput that would get populated with different contents dependent on the chosen item in the left sidebar. Note that this is a partial solution. The sidebar, once expanded, will still not collapse when selecting section C in the left sidebar. [See edit below that addresses collapsing of the right sidebar.]

library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)

ui <- dashboardPagePlus(
  useShinyjs(),
  header = dashboardHeaderPlus(
    title = "Dashboard",
    enable_rightsidebar = TRUE,
    rightSidebarIcon = "info-circle"
  ),
  sidebar = dashboardSidebar(
    sidebarMenu(
      menuItem("Section A", tabName = "Section_A", icon = icon("map")),
      menuItem("Section B", tabName = "Section_B", icon = icon("chart-line")),
      menuItem("Section C", tabName = "Section_C", icon = icon( "gears")),
      id = "nav"
    )
  ),
  body = dashboardBody(
    shinyDashboardThemes(
      theme = "grey_dark"
    ),
    tabItems(
      tabItem(
        tabName = "Section_A",
        p("Some content for section A")),
      tabItem(
        tabName = "Section_B",
        p("Some content for section B")),
      tabItem(
        tabName = "Section_C",
        p("Some content for section C"))
    )
  ),
  rightsidebar = rightSidebar(
    background = "dark",
    uiOutput("side_bar"),
    title = "Right Sidebar"
  )
)

server <- function(input, output) {
  observe({
    if (req(input$nav) == "Section_A"){
      message("Section A has been selected")
      # added in edit
      shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
      output$side_bar <- renderUI({
        rightSidebarTabContent(
          id = "T_A",
          title = "Tab for section A",
          p("Some content relevant for section A"),
          sliderInput(
            "obs",
            "Number of observations:",
            min = 0, max = 1000, value = 500
          )
        )
      })
    }
    if (req(input$nav) == "Section_B"){
      message("Section B has been selected")
      # added in edit
      shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
      output$side_bar <- renderUI({
        rightSidebarTabContent(
          id = "T_B",
          title = "Tab for section B",
          p("Some content relevant for section B"),
          textInput("caption", "Caption", "Data Summary")
        )
      })
    }

    if (req(input$nav) == "Section_C"){
      message("Section C has been selected")
      # added in edit
      shinyjs::removeClass(selector = "aside.control-sidebar", class = "control-sidebar-open")

      output$side_bar <- renderUI({ div() })
    }
  })
}


shinyApp(ui = ui, server = server)

Edit: Collapse the right sidebar when section C is clicked. After reading the post you linked more carefully, you can simply add

shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")

in your observer when section A and section B are selected, and add

shinyjs::removeClass(selector = "aside.control-sidebar", class = "control-sidebar-open")

when section C is selected.

Then the right sidebar will expand and collapse based on selections in the left sidebar.

A gif of the behavior:

enter image description here

like image 186
teofil Avatar answered May 16 '23 09:05

teofil


Adding to teofil's answer, you can use selector = "body" instead so the right sidebar can still be opened and closed.

shinyjs::addClass(selector = "body", class = "control-sidebar-open")
shinyjs::removeClass(selector = "body", class = "control-sidebar-open")
like image 36
CPB Avatar answered May 16 '23 09:05

CPB