2

The app below contains an actionButton, a shinyWidgets::progressBar and a selectInput:

enter image description here

When the Start button is clicked, an observeEvent is triggered in which I loop through the numbers 1-10 and increment the progress bar at each iteration. I would also like to update the value of the selectInput at each iteration but updateSelectInput does not work as expected. Instead of updating in tandem with the progress bar, the selectInput value is only updated once the loop has terminated. I don't understand why updateProgressBar works here but updateSelectInput doesn't?

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  actionButton(inputId = "go", label = "Start"), #, onclick = "$('#my-modal').modal().focus();"
  shinyWidgets::progressBar(id = "pb", value = 0, display_pct = TRUE),
  selectInput('letters', 'choose', letters)
)

server <- function(input, output, session) {

  observeEvent(input$go, {

    shinyWidgets::updateProgressBar(session = session, id = "pb", value = 0) # reinitialize to 0 if you run the calculation several times

    for (i in 1:10) {

      updateProgressBar(session = session, id = "pb", value = 100/10*i)

      updateSelectInput(session, 'letters', selected = letters[i])

      Sys.sleep(.5)

    }

  })

}

shinyApp(ui = ui, server = server)
user51462
  • 1,658
  • 2
  • 13
  • 41
  • 1
    Hi, I tried to use ```withProgress``` and ```incProgress``` (see [here](https://shiny.rstudio.com/articles/progress.html)) but it doesn't work either. But in fact I'm wondering: why would you want ```selectInput``` to update automatically if it stops at the letter "j" (since it is the tenth letter)? – bretauv Jan 18 '20 at 13:44
  • 1
    This behavior doesn't seem to work with any of the `updateFooInput` functions inside a for-loop (I tested radio buttons, text etc). As far as I can tell, the only internal difference is calling `session$sendInputMessage()` vs calling `session$sendCustomMessage()`. – Brian Jan 18 '20 at 21:04
  • 1
    I'd recommend asking this on the RStudio Community forum (https://community.rstudio.com/c/shiny), since this isn't about the progress bar, but the behavior of `sendInputMessage()` inside a for-loop, and there may be some good advice there. – Brian Jan 18 '20 at 21:40
  • @bretauv, thanks for looking into that. The app uses multiple progress indicators at different places on the page and I would have preferred to use `withProgress` but it doesn't allow me to change the position of a specific prog bar. I know how to change position using CSS but I would have to use a class rule `.shiny-notification {...}` that would apply to all progress indicators in my app. I used a `selectInput` just as a toy example. In the actual app, I am updating some text using `removeUI` and `insertUI` but the behaviour is the same. – user51462 Jan 18 '20 at 23:20
  • Thanks for your suggestion @Brian. That's an interesting observation regarding sendInputMessage() vs sendCustomMessage(). My actual app udpates some text beneath the progressBar using `insertUI` and `removeUI`. These use `session$sendInsertUI` and `session$onFlushed` internally but the behaviour is the same as the `updateSelectInput`. – user51462 Jan 18 '20 at 23:26
  • @Brian I've posted it here: https://community.rstudio.com/t/r-shiny-the-behaviour-of-sendinputmessage-vs-sendcustommessage-inside-a-for-loop/49834. – user51462 Jan 18 '20 at 23:59

1 Answers1

1

It works if I set immediate = T in removeUI and insertUI. I got the idea from this post - it doesn't explain why immediate = T is needed though. According to the help page:

Immediate - whether the UI object should be immediately inserted into the app when you call insertUI, or whether Shiny should wait until all outputs have been updated and all observers have been run (default).

But I don't understand what this means in the context of the for-loop. Does it have something to do with the scope of the for-loop?

If someone could post an explanation here I will accept their answer.

Updated code:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  actionButton(inputId = "go", label = "Start"), #, onclick = "$('#my-modal').modal().focus();"
  shinyWidgets::progressBar(id = "pb", value = 0, display_pct = TRUE),
  div(id = 'placeholder')
)

server <- function(input, output, session) {

  observeEvent(input$go, {

    shinyWidgets::updateProgressBar(session = session, id = "pb", value = 0) # reinitialize to 0 if you run the calculation several times

    for (i in 1:10) {

      updateProgressBar(session = session, id = "pb", value = 100/10*i)

      removeUI('#text', immediate = T)

      insertUI('#placeholder', ui = tags$p(id = 'text', paste('iteration:', i)), immediate = T)

      Sys.sleep(1)

    }

  })

}

shinyApp(ui = ui, server = server)
user51462
  • 1,658
  • 2
  • 13
  • 41