Disable Shiny Plots that Need to be Recalculated

Viewed 159

So here's my problem:

  1. My shiny app has multiple graphs and maps and using the simple reactive model means it recalcs the plots ever time a checkbox is changed - too slow when the user may want to change more than one option.
  2. I've setup isolation and a "go button" as described in Stop reactions with isolate()
  3. I have more than one "row" of filters and graphs - basically I have two groups of filters that update their corresponding graphs.

The problem:

  • I want to show the user that the graphs are "out of date" when they change an input value so they are prompted to recalculate with the "go" button.

I've tried:

  • Using javascript handler on input/select change to add .recalculating to the plots. However when one of the go buttons is pressed, it recalculates only the plots related to that button BUT it removes the .recalculating class from ALL plots (even though some have not been recalculated).

Workaround is to have either go button update all plots but that's not ideal from a resource standpoint.

To reproduce use the code below and:

  1. Click both buttons to generate the graphs.
  2. Change both filters (checkbox and radio) which will show both graphs as needing recalculating.
  3. Press just one button to regenerate graphs.
  4. See that both graphs appear to be recalculated when only one has in fact changed.

Here's a working example of how my shiny app is organized:

library('shiny')
library('ggplot2')

ui <- fluidPage(
  checkboxGroupInput(inputId = 'cyl', label = 'Cylinders:', choices = unique(mtcars$cyl), selected = unique(mtcars$cyl)),
  actionButton('goButton', 'Update graph!'),
  plotOutput('plot'),
  radioButtons(inputId = 'vs', label = 'V-shaped 09:', choices = unique(mtcars$vs), selected = 1),
  actionButton('goButton2', 'Update 2nd graph!'),
  plotOutput('plot2'),
  #change handlers
  tags$script(HTML("$(document).on('change', 'input, select', function(event) {
      $('.shiny-bound-output').addClass('recalculating')
                   })"))
)

server <- function(input, output) {
  #first data.frame - cyl
  df <- reactive({
    mtcars[mtcars$cyl %in% input$cyl,]
  })
  #second data frame - vs9
  df2 <- reactive({
    mtcars[mtcars$vs == input$vs,]
  })
  output$plot <- renderPlot({
    #only run if goButton pressed
    if (input$goButton == 0) 
      return()
    isolate({
      ggplot(df(), aes(x=hp, y=disp)) +
        geom_point()
    })
  })
  output$plot2 <- renderPlot({
    #only update if goButton2 pressed
    if(input$goButton2 == 0)
      return()
    isolate({
      ggplot(df2(), aes(x=hp, y=disp)) +
        geom_point()
    })
  })
}

shinyApp(ui, server)
0 Answers
Related