1

I'm trying to update a uiOutput using the change in reactiveValues from inside a loop, but it doesn't seem to work. I've looked into some answers, but they're all trying to work it from inside output$somthing, which is not the case here: like those:

Update shiny output within loop

For loop inside output in Shiny

Here some reproducible app.

vars = reactiveValues(cc="",ct=0)
ui = fluidRow(uiOutput("warngt"),actionButton("searchgt","Search"))
server = function(input, output, session){
  observeEvent(input$searchgt,{
    if(vars$ct<10){
      repeat{
        vars$ct=vars$ct+1
        vars$cc=paste(sprintf('<b style="color:blue">',"Searching...[%s]",vars$ct),"</b>");Sys.sleep(.5)
        #This also does not work:
        #output$warngt=renderUI({HTML(vars$cc)})
        vars$busca = try(print("Something"),silent = T)
        if(vars$ct==10){break}
      }
    }else{
      #This work just fine
      vars$cc=paste('<b style="color:red">',"Some warning.","</b>")
    }
    #This also doesn't work
    #output$warngt=renderUI({HTML(vars$cc)})
  })
  output$warngt = renderUI({HTML(vars$cc)})
}
shinyApp(ui = ui, server = server)

Thanks in advance!

  • 1
    Your understanding on how shiny works is incorrect. You cannot update UI in a loop because all renders/observers execute only after a previous observer get executed. The `repeat` loop doesn't work because that `observeEvent` is always occupying the session. You need to use `invalidateLater` instead. The following resources should help you solve your problem: https://stackoverflow.com/questions/43244988/shiny-how-to-stop-processing-invalidatelater-after-data-was-abtained-or-at-th – yusuzech Sep 26 '19 at 23:04

1 Answers1

1

I rewrote your sever codes to make it working.

You cannot update UI in a loop as I already mentioned in the comment, it isn't how Shiny works. Use invalidateLater() to do something similar to a for loop.

And also, invalidateLater() doesn't work in observeEvent, so you need to write the loop logic in observe()

isolate() is used to prevent recursive triggering of the observer, so it only re-evaluate every 0.5 second based on invalidateLater(500)

server = function(input, output, session){
  vars = reactiveValues(cc="",ct=0)
  startSearch <- reactiveVal(FALSE)
  startSearch <- eventReactive(input$searchgt,{
    TRUE
  })

  observe({
    req(startSearch())
    if (isolate(vars$ct) < 10){
      invalidateLater(500)
      isolate({
        vars$ct=vars$ct+1
        vars$cc=paste('<b style="color:blue">',"Searching...",vars$ct,"</b>")
        vars$busca = try(print("Something"),silent = T)
      })
    } else {
      vars$cc=paste('<b style="color:red">',"Some warning.","</b>")
    }

  })

  output$warngt = renderUI({HTML(vars$cc)})
}
yusuzech
  • 5,896
  • 1
  • 18
  • 33