2

I have a very large app. To help it load more efficiently, I have put a lot of the data processing into an observeEvent() function. What I am hoping to add is a slider input to change bin size on a histogram with reactive values.

How can I make the plot update without having to hit the action button again?

Here is a sample app:

library(shiny)
library(ggplot2)

ui <- basicPage(
  actionButton("launch", "Launch"),
  uiOutput("plotInteractive")
  )

server <- function(input, output) {
  bins <- reactive({input$binsize})
  
  observeEvent(input$launch, {
  plot <- ggplot(diamonds, aes(y = carat)) +
            geom_histogram(bins = bins())
  
  output$plotInteractive <- renderUI ({
    tagList(
      renderPlot(plot),
      sliderInput(inputId = "binsize", label = "Bin Size", min = 1, max = 40, value = 20)
      )
  }) #end UI
  }) #end observe
} #end server

shinyApp(ui, server)
Derrick
  • 21
  • 2
  • Thank you, this was really helpful and lead me to the answer that fit with my app. You are right: I had to move the renderPlot function from its location. The problem was not that it was in the observeEvent, rather, it was nested inside the renderUI. – Derrick Oct 10 '21 at 04:56

2 Answers2

0

Don't include renderPlot in observeEvent because if you do the code would be executed only when you click on the Launch button.

I am not sure why you have sliderInput in the server side since it seems static but maybe it makes sense in the larger app.

library(shiny)
library(ggplot2)

ui <- basicPage(
  actionButton("launch", "Launch"),
  plotOutput('plot'),
  uiOutput("plotInteractive")
)

server <- function(input, output) {
  bins <- reactive({input$binsize})
  
  output$plot <- renderPlot({
    req(input$launch) #Show plot only after launch is clicked
    ggplot(diamonds, aes(y = carat)) +
    geom_histogram(bins = bins())
  })
  
  observeEvent(input$launch, {
    output$plotInteractive <- renderUI ({
        sliderInput(inputId = "binsize", label = "Bin Size", 
                    min = 1, max = 40, value = 20)
    }) #end UI
  }) #end observe
} #end server

shinyApp(ui, server)

enter image description here

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
0

The easiest solution is to just move the renderPlot from the renderUI function and instead define plot <- renderPlot({ggplot...})

Code below:

library(shiny)
library(ggplot2)

ui <- basicPage(
  actionButton("launch", "Launch"),
  uiOutput("plotInteractive")
  )

server <- function(input, output, session) {
  
  observeEvent(input$launch, {
    bins <- reactive({input$binsize})
    
    plot <- renderPlot({
      ggplot(diamonds, aes(y = carat)) +
            geom_histogram(bins = bins())
    })
  
  output$plotInteractive <- renderUI ({
    tagList(
      plot,
      sliderInput(inputId = "binsize", label = "Bin Size", min = 1, max = 40, value = 20)
      )
  }) #end UI
  }) #end run
  
} #end server

shinyApp(ui, server)
Derrick
  • 21
  • 2