0

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
      }
  })
Tingolfin
  • 825
  • 8
  • 28

1 Answers1

1

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))
T.Holme
  • 473
  • 4
  • 17
  • I'm currently trying your solution. I tried your last script to understand the code, but it doesn't work. I don't get a plot (plotOutput is missing in ui). But when I add `plotOutput("plotTemp")` and then run it, the plot already appears before I click the button. Is there something else missing? – Tingolfin Nov 28 '16 at 08:34
  • I think I've misunderstood your question. The plot title will only update when you hit the button. – T.Holme Nov 28 '16 at 11:22
  • 1
    If you want there to be no plot when you start the app, put `if(input$button=0){return(NULL))` at the beginning of your renderPlot – T.Holme Nov 28 '16 at 11:23
  • 1
    Having a nightmare `if(input$button==0){return(NULL)}`. Too early! – T.Holme Nov 28 '16 at 11:24
  • Ok so I did what you suggested and it works nicely, thank you! I have one more question now. I have a second plot in my app, showing population dynamics of a species. The user choses via selectInput which species he wants to see. No plot is shown when the app starts, but when the button is clicked the plot of the chosen species shows. When another species is selected, the plot should show immediately, without clicking the button because no date or station input has changed. I'm confused with the order there (adding this to my original post too + code) – Tingolfin Nov 28 '16 at 13:13