2
votes

When making shiny apps I often struggle with how to arrange plots and text outputs on the page for the user. So, I like to try an make it possible for a user to select which output to display. For instance, the user may be able to display 3 graphs and 2 chunks of text but may only want to display the first graph and one chunk of text. I can usually accomplish this using if statements inside of render functions. But, I have found shiny will still add white space even if...the user does not indicate the plot should be displayed. This appears to be some sort of placeholder space that ends up leaving big holes in the app. In my example, the app displays the 2nd plot, but there is a big piece of white space that makes the page look ugly.

I have found this: Shiny: unwanted space added by plotOutput() and/or renderPlot() whihc doesnot quite apply. There doesn't seem to be a post that addresses this specific problem.

library(shiny)

ui <- fluidPage(

   titlePanel("Old Faithful Geyser Data"),

   sidebarLayout(
      sidebarPanel(
         sliderInput("bins",
                     "Number of bins:",
                     min = 1,
                     max = 50,
                     value = 30)),
      mainPanel(
         plotOutput("distPlot"),
         plotOutput("distPlot2"))))


server <- function(input, output) {

   output$distPlot <- renderPlot({
      if(input$bins == 4){
      x    <- faithful[, 2] 
      bins <- seq(min(x), max(x), length.out = input$bins + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
   }})

   output$distPlot2 <- renderPlot({
      x    <- faithful[, 2] 
      bins <- seq(min(x), max(x), length.out = input$bins + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')})
   }

shinyApp(ui = ui, server = server)
1

1 Answers

1
votes

In this particular case, two possible options are to either wrap the first plot in a shiny::conditionalPanel() or make use of shiny::renderUI().

shiny::conditionalPanel() Example

library(shiny)

ui <- fluidPage(

  titlePanel("Old Faithful Geyser Data"),

  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)),
    mainPanel(
      conditionalPanel("input.bins == 4", plotOutput("distPlot")),
      plotOutput("distPlot2"))))

server <- function(input, output) {

  output$distPlot <- renderPlot({
      x    <- faithful[, 2] 
      bins <- seq(min(x), max(x), length.out = input$bins + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })

  output$distPlot2 <- renderPlot({
    x    <- faithful[, 2] 
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = 'darkgray', border = 'white')})
}

shinyApp(ui = ui, server = server)

shiny::renderUI() Example

library(shiny)

ui <- fluidPage(

  titlePanel("Old Faithful Geyser Data"),

  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)),
    mainPanel(
      uiOutput("distPlots"))))


server <- function(input, output) {
  output$distPlot <- renderPlot({
      x    <- faithful[, 2] 
      bins <- seq(min(x), max(x), length.out = input$bins + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })

  output$distPlot2 <- renderPlot({
    x    <- faithful[, 2] 
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins, col = 'darkgray', border = 'white')})

  output$distPlots <- renderUI({
    if(input$bins == 4)
      fluidPage(plotOutput("distPlot"), plotOutput("distPlot2"))
    else
      plotOutput("distPlot2")
  })
}

shinyApp(ui = ui, server = server)

Both approaches produce this:

output of either approach