4
votes

since couple of days I am trying to find solution to plot appearing wrongly (beyond box width) in shiny app while using function show/hide sidebar.

Here is example code:

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

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    extendShinyjs(text = 'shinyjs.hideSidebar = function(params) { $("body").addClass("sidebar-collapse") }'),
    extendShinyjs(text='shinyjs.showSidebar = function(params) { $("body").removeClass("sidebar-collapse") }'),
    fluidRow(tabsetPanel(id='tabs',
                         tabPanel(value=1,title="Plot1",
                                  fluidRow(
                                    column(12,
                                  plotOutput('plot1', height=800)))),
                         tabPanel(value=2, title="Plot2",
                                  fluidRow(
                                    column(12,
                                  plotOutput('plot2', height=800))))
             )
      )))
  )
)

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

  observe({
    if (input$tabs == 1) {
      js$hideSidebar()
    }
    else {
      js$showSidebar()
    }
  })
}

shinyApp(ui, server)

As we can see in this example code, i would like the sidebar to appear when the user opens the second tab (sidebar collapsed when input$tabs == 1). It is working pretty good, except when i press to see tab2, then go back to tab1 and again to tab2, the plot is resized and the x axis is cut:

enter image description here

2
You are redefining the dataset you plot every time you click the tabs because the call to rnorm() is in renderPlot. Isn't that the source of your problem? - ddiez
Oh, I retract my previous comment. I used a fixed dataset and now got your point (might be better to do so in your example to remove confusion caused by the plot changing). - ddiez
Just an unrelated side comment: you can define both the js functions in one call/in one string. You don't need to call extendShinyjs() twice - DeanAttali

2 Answers

3
votes

A "hacky" way to do this is to trigger a window resize event when you add/remove the sidebar to force the plot to be redrawn at the right size after the sidebar is shown/hidden:

extendShinyjs(text = 'shinyjs.hideSidebar = function(params) { $("body").addClass("sidebar-collapse"); 
              $(window).trigger("resize"); }'),
extendShinyjs(text='shinyjs.showSidebar = function(params) { $("body").removeClass("sidebar-collapse"); 
              $(window).trigger("resize"); }')
0
votes

I do not of a correct fix to this issue but a workaround is to set also width in your call to plotOutput() (e.g. I tried width=800). Then the dimensions of the plot will be fixed and (once the window is resized to the appropriate dimensions) the plot is not cut.