12

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
  • 6,405
  • 6
  • 28
  • 69
needRhelp
  • 2,948
  • 2
  • 24
  • 48
  • You almost got it right. `class` should be `sidebar-collapse` instead of `sidebarPanel-collapse`. HTH – Tom May 09 '23 at 08:21

4 Answers4

18

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
  • 27,060
  • 21
  • 118
  • 148
SBista
  • 7,479
  • 1
  • 27
  • 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
5

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
  • 303
  • 2
  • 9
3

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)
Takuro Ikeda
  • 158
  • 6
  • 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
  • 2
    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
0

automatically collapse the sidebarPanel shinyjs::runjs("$('.sidebar-toggle').click();")

kraggle
  • 196
  • 2
  • 9
  • Where to put this ? – Julien Jul 21 '23 at 10:17
  • In a reactive or observer whenever you want the action to happen. – kraggle Jul 21 '23 at 10:19
  • could even put it inside a `render` operation, which is what I did. When the app opens I want the user to login, nothing else is seen and the sidebarPanel is collapsed. Then after a successful login, the LDAP credentials of the user with their thumbnail photo are displayed, and sidebar toggle click to display. – kraggle Jul 21 '23 at 14:38