Progress Bar

#| standalone: true
#| components: [viewer]
#| viewerHeight: 200

library(shiny)
library(bslib)

ui <- page_fluid(
  actionButton("run", "Compute"),
  textOutput("txt")
)

server <- function(input, output, session) {
  text <- reactiveVal()
  output$txt <- renderText({ text() })

  observe({
    withProgress( 
      message = 'Calculation in progress', 
      detail = 'This may take a while...', 
      value = 0, 
      {
        for (i in 1:15) { 
          incProgress(1/15) 
          Sys.sleep(0.25) 
        } 
        text("Done computing!") 
      } 
    ) 
  }) |>
    bindEvent(input$run)
}

shinyApp(ui, server)
library(shiny)
library(bslib)

ui <- page_fluid(
  actionButton("run", "Compute"),
  textOutput("txt")
)

server <- function(input, output, session) {
  text <- reactiveVal()
  output$txt <- renderText({ text() })

  observe({
    withProgress( 
      message = 'Calculation in progress', 
      detail = 'This may take a while...', 
      value = 0, 
      {
        for (i in 1:15) { 
          incProgress(1/15) 
          Sys.sleep(0.25) 
        } 
        text("Done computing!") 
      } 
    ) 
  }) |>
    bindEvent(input$run)
}

shinyApp(ui, server)
No matching items

Relevant Functions

  • withProgress
    withProgress(expr, min = 0, max = 1, value = min + (max - min) * 0.1, message = NULL, detail = NULL, style = getShinyOption("progress.style", default = "notification"), session = getDefaultReactiveDomain(), env = parent.frame(), quoted = FALSE)

  • incProgress
    incProgress(amount = 0.1, message = NULL, detail = NULL, session = getDefaultReactiveDomain())

  • setProgress
    setProgress(value = NULL, message = NULL, detail = NULL, session = getDefaultReactiveDomain())

  • Progress
    Progress

No matching items

Details

With Shiny, you can display a progress bar while a computation runs by running the computation within a special function. Here’s how:

  1. Wrap the computation to run in withProgress(). withProgress() creates a panel with a progress bar that is displayed during the computation. For example, you might set up a progress bar like this:
withProgress(
  min = 1,
  max = 15, 
  #  computation
)
  1. Set the minimum and maximum values of the progress bar when you call withProgress(). These provide the outer bounds for the progress to display. For example, in the code above, when the bar is at 1, it would appear empty. When it is at 8, it would appear half full. When it is at 15, it would appear complete.

  2. Update the progress bar object as the computation runs. Updating the object is simple: you can call setProgress() or incProgress() from within the computation to change the location of the progress bar, as well as the message it displays. For example the code below would update the progress bar above to half finished, and change the message that accompanies the bar to “Almost there!”.

setProgress(8, message = "Almost there")

Finding opportunities to update the bar while the computation runs is more tricky. To have a responsive bar, you will need to interlace set calls with the computation that runs. If the computation is a function from an external package, you may only be able to alert the user when the computation begins and when it finishes, which is unlikely to be satisfying:

withProgress(
  min=1, 
  max=15,
  {
    setProgress(1, message = "Here we go")
    # computation()
    setProgress(15, message = "Finished!")
  }
)

If the computation involves separate functions run in sequence, you can update the progress bar after each function:

withProgress(
  min=1, 
  max=15,
  {
    setProgress(1, message = "Here we go")
    # computation1()
    setProgress(5, message = "Working hard")
    # computation2()
    setProgress(10, message = "Almost there")
    # computation3()
    setProgress(15, message = "Finished!")
  }
)

If the computation is a function that you have written, you can write the function to accept a progress bar object to update as it runs. To do this, use Progress/ Progress provides an alternative, object-oriented API for building a progress bar in Shiny.