textOutput/ActionButton are not updating after executing renderText/updateActionButton

802 views
Skip to first unread message

Luis Gustavo Nardin

unread,
Feb 27, 2017, 9:12:03 PM2/27/17
to Shiny - Web Framework for R, inskee...@gmail.com, bech...@vandals.uidaho.edu, gna...@uidaho.edu
Hello,
I am using Shiny v0.14.1 and R 3.3.2 to implement a simulation. The simulation executes in time steps and because I want to allow people to stop the simulation before it finishes, I used observeEvent to create a sort of loop (it is working). The simulation, however, needs to update a text output at each time step but the user interface is not updated at each time step, only at the end of the simulation. The same occurs with the label of the button that does not change until the end of the simulation.

If you look at the sequence of commands, you will see that the updateActionButton, for instance, is executed before the update of the variable that triggers the next observeEvent, but still the button changes label only at the end of the simulation.

I have already tried to use priority in the observeEvent, include Sys.sleep inside the observeEvent (I think it is wrong), and invalidateLater inside the renderText, but nothing worked.

Below I include a simplified version of the code with problem. The desired output would be to see the number in the Main Panel increasing as the values$step increases, but the number freezes in 1 and at the end of the simulation it updates to the number set in the "Time steps" numeric field.

shinyUI(fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput("steps", "Time steps:", 500, min=1),
      actionButton("run", label="Start")
    ),
  
    mainPanel(
       textOutput("Status")
    )
  )
))


shinyServer(function(input, output, session) {
 
  values <- reactiveValues(running=FALSE, step=1)
  start <- 0
 
  observeEvent(input$run, {
    if(input$run > start){
      updateActionButton(session, "run", label = "Stop")
      values$running <<- TRUE
      start <<- input$run + 1
    } else if(input$run > 0){
      updateActionButton(session, "run", label = "Resume")
      values$running <<- FALSE
    }
  })
 
  observeEvent(c(values$running, values$step), {
    if(values$running & values$step < input$steps){
        values$step <<- values$step + 1
    }
  })
 
  output$Status <- renderText({
    values$step
  })
})

Am I using correctly the observeEvent? I tried observe and eventReactive, but I was also not successful.

Thank you in advance,
Gustavo

Bárbara Borges

unread,
Feb 28, 2017, 12:03:47 PM2/28/17
to Shiny - Web Framework for R, inskee...@gmail.com, bech...@vandals.uidaho.edu, gna...@uidaho.edu
You can do something like this:

library(shiny)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput("steps", "Time steps:", 10, min=1),
      actionButton("run", label="Start")
    ),
    mainPanel(
      textOutput("status")
    )
  )
)


server <- function(input, output, session) {
  
  vals <- reactiveValues(running = FALSE, step = 0, run = 1, label = "Start")
  
  # helper functions
  toggleLabel <- function() {
    if (vals$label %in% c("Start", "Resume")) vals$label <- "Stop"
    else vals$label <- "Resume"
    vals$label
  }
  
  observe({
    req(input$run)

    isolate({
      # update label when the button is clicked and stop/resume computation
      if (input$run != vals$run) {
        updateActionButton(session, "run", label = toggleLabel())
        vals$run <- input$run
        vals$running <- !vals$running
      }
      
      # update label and vals$running the first time around only
      if (vals$label == "Start") {
        updateActionButton(session, "run", label = toggleLabel())
        vals$running <- TRUE
      }
    })
    
    # If we're not done yet, then schedule this block to execute again ASAP.
    # Note that we can be interrupted by other reactive updates to, for
    # instance, update a text output.
    if (isolate({ (vals$step < input$steps) && vals$running })) {
      Sys.sleep(1) # placeholder for computation
      vals$step <- isolate(vals$step) + 1
      invalidateLater(0, session)
    }
  })

  output$status <- renderText({
    paste("You're on iteration number:", vals$step)
  })
}

shinyApp(ui, server)

This is based on Jeff Allen's gist: https://gist.github.com/trestletech/8608815

Luis Gustavo Nardin

unread,
Feb 28, 2017, 12:22:32 PM2/28/17
to Bárbara Borges, Shiny - Web Framework for R, inskee...@gmail.com, bech...@vandals.uidaho.edu, Luis Gustavo Nardin
Dear Barbara,
Excellent!
Thank you very much for your help,
Gustavo

--
You received this message because you are subscribed to a topic in the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/shiny-discuss/21mNqt8rsLY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to shiny-discuss+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/shiny-discuss/4103e1e4-8d98-4ced-99b4-a0f43fada4f5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Luis Gustavo Nardin
Reply all
Reply to author
Forward
0 new messages