0
votes

In my app users enter 3 elements (year, date, station), click an actionButton and get a temperature plot. Without a button the app was slow and with every input change a new plot was made. So I added the button, but I'm not sure if I did this properly. I made seperate eventReactive for all inputs, but can't I put them together? I tried a few things, but couldn't figure it out.

I need this because I'm trying to implement this guy's "loading" and "done" gifs (my app is so slow, people need to be reassured something is happening):

https://github.com/daattali/advanced-shiny/tree/master/busy-indicator

But with the separate reactive events the gifs reappeard and disappear with each step and they have to stay during the whole actionButton process.

EDIT Thanks to T.Holme I inserted isolate(). But before I try to implement the gifs, I have to adjust a second part and I'm struggling there.

EDIT 2 I just learned that to avoid running everything inside renderPlot at the start of the app, you can use req(input$button) instead of

if(input$button == 0){return(NULL)} 
input$button

The if solution rendered an empty white rectangle (where the plot will come), while with req(), nothing happens/appears before you click. Thought this might help other people too.

My corrected code:

ui <- fluidPage(
  selectInput("jaartal" , choices = 2014:2100, selected = format(Sys.Date(), "%Y")),
  uiOutput("datums")
  selectInput("weerstation", choices = list("ALDENEIK", "ALKEN")),
  actionButton("button", label = "Bereken"),
  plotOutput("plotTemp")
)

server <- function(input, output){
  # datum range
  output$datums <- renderUI({
    dateRangeInput("datums", label = h4("Periode"), 
                   start = paste(input$jaartal, "-01-01", sep = ""),
                   end = paste(input$jaartal, format(Sys.Date(), "%m"),
                               format(Sys.Date(), "%d"), sep = "-"),
                   min = paste(input$jaartal, "-01-01", sep = ""), 
                   max = paste(input$jaartal, "-12-31", sep = ""))
  })

  # plot temperatuur
  output$plotTemp <- renderPlot({
    req(input$button)
    isolate({
      importdata(input$jaartal)
      weerstation <- which(weerstations == input$weerstation)
      temperatuur(input$datums, weerstation)
    })
  })

My app shows a 2nd plot with population dynamics of a chosen species. It worked like this with my old code: 1) no plots at start. 2) with a buttonclick, the temp and population plots are made. 3) select another species and the plot adjusts immediately without the button. 4) when other input (date, station) changes, the user has to click the button to adjust both plots.

Currently requirements 1), 2) and 3) are fullfilled, but 4) isn't. When I change the station the plot doesn't move = good, but when I change year or date the population plot adjusts = not good. Any ideas?

output$plotSoort <- renderPlot({
    req(input$button)
    isolate({
      importdata(input$jaartal)
      weerstation <- which(weerstations == input$weerstation)
      temperatuur(input$datums, weerstation)})
      if(input$populatie == "PER"){            
        perenbladvlo(input$datums, weerstation) # 1st species model
      }                                        
      else if(input$populatie == "OOR"){
        oorworm(input$datums, weerstation) # 2nd species model
      }
      else if(input$populatie == "FLU"){
        fluweelmijt(input$datums, weerstation) # 3rd species model
      }
  })
1

1 Answers

1
votes

You can change your render plot function to the following:

  output$plotTemp <- renderPlot({
    input$button
    isolate({
      importdata(inputJaar())
      temperatuur(inputDatum(), inputStation())
    })
  })

The code in the isolate will only be run when the value of input$button changes. This is a key part of reactive programming.

To demonstrate this, run the following script (edited following comments below):

library(shiny)

ui <- shinyUI(fluidPage(
  selectInput("jaartal" , label = h4("Jaar"), choices = 2014:2100, selected = format(Sys.Date(), "%Y")),
  actionButton("button", label = "Bereken"),
  plotOutput("plotTemp")

))

server <- shinyServer(function(input, output){
  # datum range

  output$plotTemp <- renderPlot({
    if(input$button == 0){return(NULL)}

    input$button
    isolate({
      plot(x = 1:100,y=101:200)
        title(main=input$jaartal)
    })
  })
})

runApp(shinyApp(ui,server))