11

I have a shiny app with a mainPanel and a sidebarPanel inside a tabPanel in a navbarPage. I need an option to hide the sidebarPanel similar to this: Hide sidebar in default in shinydashboard and https://github.com/daattali/shinyjs/issues/43.

An actionButton should control if the sidebarPanel is shown or collapsed.

This is the code:

library(shiny)
library(shinyjs)

ui <- fluidPage(
  navbarPage("",
             tabPanel("tab",
                      sidebarPanel(
                        useShinyjs()
                      ),
                  
                      mainPanel(actionButton("showSidebar", "Show sidebar"),
                                actionButton("hideSidebar", "Hide sidebar")
                      )
             )
  )
)

server <-function(input, output, session) {
  observeEvent(input$showSidebar, {
    shinyjs::removeClass(selector = "body", class = "sidebarPanel-collapse")
  })
  observeEvent(input$hideSidebar, {
    shinyjs::addClass(selector = "body", class = "sidebarPanel-collapse")
  })
}

shinyApp(ui, server)
Nimantha
  • 5,793
  • 5
  • 23
  • 56
needRhelp
  • 2,683
  • 1
  • 19
  • 41

3 Answers3

17

I have modified your code to hide and show the sidebar. To create the id for the sidebarPanelI have enclosed it within div and given it theid = Sidebar. To show and hide the side bar I have used shinyjs function show and hide with the id as Sidebar.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  navbarPage("",
             tabPanel("tab",
                      div( id ="Sidebar",sidebarPanel(
                      )),
                      
                      
                      mainPanel(actionButton("showSidebar", "Show sidebar"),
                                actionButton("hideSidebar", "Hide sidebar")
                      )
             )
  )
)

server <-function(input, output, session) {
  observeEvent(input$showSidebar, {
    shinyjs::show(id = "Sidebar")
  })
  observeEvent(input$hideSidebar, {
    shinyjs::hide(id = "Sidebar")
  })
}

shinyApp(ui, server)
Zoe stands with Ukraine
  • 25,310
  • 18
  • 114
  • 149
SBista
  • 6,969
  • 1
  • 25
  • 58
  • nice answer, thanks (+1), but it might be better to use `shinyjs::toggle` with only one button – Antoine Mar 23 '18 at 12:15
  • Yes that would definitely be a better option. The answer was just inline withe question asked and the code that was provided. I'll definitely edit my answer with your suggestion very soon. – SBista Mar 23 '18 at 12:19
4

An example of the toggle option suggested in previous comments.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  navbarPage("",
             tabPanel("tab",
                      div( id ="Sidebar",sidebarPanel(
                      )),


                      mainPanel(actionButton("toggleSidebar", "Toggle sidebar")
                      )
             )
  )
)

server <-function(input, output, session) {
  observeEvent(input$toggleSidebar, {
    shinyjs::toggle(id = "Sidebar")
  })
}

shinyApp(ui, server)
Harrison
  • 193
  • 8
2

I made an example with toggle button on navbar and multiple tabs.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  navbarPage(title = tagList("title",actionLink("sidebar_button","",icon = icon("bars"))),
             id = "navbarID",
             tabPanel("tab1",
                      div(class="sidebar"
                          ,sidebarPanel("sidebar1")
                      ),
                      mainPanel(
                        "MainPanel1"
                      )
             ),
             tabPanel("tab2",
                      div(class="sidebar"
                          ,sidebarPanel("sidebar2")
                      ),
                      mainPanel(
                        "MainPanel2"
                      )
             )
  )
)

server <-function(input, output, session) {
  
  observeEvent(input$sidebar_button,{
    shinyjs::toggle(selector = ".sidebar")
  })
  
}

shinyApp(ui, server)

=======================================

I have created a simpler example that does not use the sidepanel class, but I am not sure if it will work in all environments.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  navbarPage(title = tagList("title",actionLink("sidebar_button","",icon = icon("bars"))),
             tabPanel("tab1",
                      sidebarPanel("sidebar1"),
                      mainPanel("MainPanel1")
             ),
             tabPanel("tab2",
                      sidebarPanel("sidebar2"),
                      mainPanel("MainPanel2")
             )
  )
)

server <-function(input, output, session) {
  observeEvent(input$sidebar_button,{
    shinyjs::toggle(selector = ".tab-pane.active div:has(> [role='complementary'])")
  })
}

shinyApp(ui, server)

=======================================

I've finally finished my collapsible sidebarpanel, and shinyjs runjs allows you to extend the width of the mainpanel when the sidebarpanel is collapsed.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  navbarPage(title = tagList("title",actionLink("sidebar_button","",icon = icon("bars"))),
             tabPanel("tab1",
                      sidebarPanel("sidebar1",width=3),
                      mainPanel("MainPanel1",width=9,style="background-color:gray")
             ),
             tabPanel("tab2",
                        sidebarPanel("sidebar2",width=5)
                        ,mainPanel("MainPanel2",width=7,style="background-color:gray")
             )
  )
)

server <-function(input, output, session) {
  observeEvent(input$sidebar_button,{
    shinyjs::toggle(selector = ".tab-pane.active div:has(> [role='complementary'])")
    
    js_maintab <- paste0('$(".tab-pane.active div[role=',"'main'",']")')
    
    runjs(paste0('
          width_percent = parseFloat(',js_maintab,'.css("width")) / parseFloat(',js_maintab,'.parent().css("width"));
          if (width_percent == 1){
            ',js_maintab,'.css("width","");
          } else {
            ',js_maintab,'.css("width","100%");
          }
          '))
  })
}

shinyApp(ui, server)
  • 1
    I was able to create an example that works well, but there is one problem: hiding the sidebarPanel does not extend the width of the mainPanel to full screen. Hiding the sidebarPanel doesn't make the mainPanel any wider, so there's less point in hiding it. Do I still have to use the shinydashboard? – Takuro Ikeda Jul 21 '21 at 13:16
  • 1
    I've finally finished my collapsible sidebarpanel, and shinyjs runjs allows you to extend the width of the mainpanel when the sidebarpanel is collapsed. Thank you. – Takuro Ikeda Jul 26 '21 at 04:43