Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating conditionally visible sidebars in shiny

Tags:

r

shiny

In R and shiny, I would like to use tabs in shinydashboard. The dashboard normally has a sidebar, but for one tab I would like to sidebar to disappear to give some more screen space to the body of the page.

I know that there are conditional panels, but is it possible to adjust the visibility of the sidebar when a tab is activated?

Below is some mock code to setup the shinydashboard with three tabs and a sidebar.

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(),
  # I would like to make the sidebar not visible if the third tab is selected...
  # something like...
  #if(input.tabs==3){dashboardSidebar(disable = TRUE)}else{dashboardSidebar()},
  dashboardSidebar(),
  if(input.tabs==3){dashboardSidebar(disable = TRUE)}else{dashboardSidebar()},
  dashboardBody(
      fluidRow(
        column(width=12,
               tabsetPanel(id='tabs'
                 tabPanel('tab1',
                          plotOutput('plot1'),value=1),
                 tabPanel('tab2',
                          plotOutput('plot2'),value=2),
                 tabPanel('tab3',
                          plotOutput('plot3'),value=3)
               )
        ))
    )
)

server <- function(input, output) { 
  output$plot1 <- renderPlot({
    out <- ggplot(data.frame(X1=rnorm(1000)),aes(X1))+
      geom_density(fill='light blue')+
      theme_minimal()
    print(out)
  })
  output$plot2 <- renderPlot({
    out <- ggplot(data.frame(X1=rnorm(1000)),aes(X1))+
      geom_density(fill='light blue')+
      theme_minimal()
      print(out)
  })
  output$plot3 <- renderPlot({
    out <- ggplot(data.frame(X1=rnorm(1000)),aes(X1))+
      geom_density(fill='light blue')+
      theme_minimal()
      print(out)
  })
}

shinyApp(ui, server)
like image 918
h.l.m Avatar asked May 23 '15 23:05

h.l.m


1 Answers

I've never used dashboards until 5 minutes ago when I saw this question, so this might not be the best answer, but it works.

It looks like when you manually "hide" the sidebar, the body tag gets a "sidebar-collapse" class. So my solution was to add javascript that adds that class to the body tag when the third tab is selected. The one downside is that when another tab is chosen, the sidebar will not re-expand, it will stay hidden until you manually expand it again.

Disclaimer: in my answer I use a package that I wrote, shinyjs.

Here is the shiny app:

library(shiny)
library(shinydashboard)
library(ggplot2)
library(shinyjs)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    extendShinyjs("app.js"),
    fluidRow(
      column(width=12,
             tabsetPanel(id='tabs',
                         tabPanel('tab1',
                                  plotOutput('plot1'),value=1),
                         tabPanel('tab2',
                                  plotOutput('plot2'),value=2),
                         tabPanel('tab3',
                                  plotOutput('plot3'),value=3)
             )
      ))
  )
)

server <- function(input, output, session) { 
  output$plot1 <- renderPlot({
    out <- ggplot(data.frame(X1=rnorm(1000)),aes(X1))+
      geom_density(fill='light blue')+
      theme_minimal()
    print(out)
  })
  output$plot2 <- renderPlot({
    out <- ggplot(data.frame(X1=rnorm(1000)),aes(X1))+
      geom_density(fill='light blue')+
      theme_minimal()
    print(out)
  })
  output$plot3 <- renderPlot({
    out <- ggplot(data.frame(X1=rnorm(1000)),aes(X1))+
      geom_density(fill='light blue')+
      theme_minimal()
    print(out)
  })

  observe({
    if (input$tabs == 3) {
      js$hideSidebar()
    }
  })
}

shinyApp(ui, server)

I only added a few lines to your app: I added calls to useShinyjs() and extendShinyjs("app.js") in the UI, and I added observe({ if (input$tabs == 3) js$hideSidebar() }) to the server. I also added the session parameter to the server function. You will also need to add a javascript file named "app.js" that contains this line:

shinyjs.hideSidebar = function(params) { $("body").addClass("sidebar-collapse") }

You can also avoid using shinyjs and use shiny's normal message passing to call a similar javascript function.

EDIT: with the latest shinyjs version 0.0.6.1 you don't need to use a separate file if you prefer to provide the javascript code inline. Simply replace the call to extendShinyjs("app.js") to

extendShinyjs(text = 'shinyjs.hideSidebar = function(params) { $("body").addClass("sidebar-collapse") }')
like image 60
DeanAttali Avatar answered Oct 01 '22 21:10

DeanAttali