waiter R Package

repository·master·Indexed 19 days ago

https://github.com/johncoene/waiter

An R package for Shiny applications to programmatically display loading screens, spinners, and progress bars. It provides several abstractions for visual feedback: 'waiter' for spinners and loading screens, 'Waitress' for progress bars, 'Attendant' for non-blocking Bootstrap progress bars, and 'Hostess' for backend progress reflection. Features include automatic loading screens via autoWaiter(), integration with httr requests, and support for Shiny modules.

Tokens
13.3K
Snippets
60
Records
64
Agent score
67%

What's inside waiter

  1. Show Waiter as partial or full screen

    master

    The scope of the loading overlay is determined by the id passed to Waiter$new():

    • Partial Overlay: Pass the id of a specific HTML element (e.g., Waiter$new("my-div-id")). The loading screen will only cover that specific element.
    • Full Screen Overlay: Call Waiter$new() without an id argument. The loading screen will cover the entire application window.
    # Partial: covers only the element with id "hello"
    w1 <- Waiter$new("hello")
    
    # Full screen: covers the whole app
    w2 <- Waiter$new()
  2. Understand the waiter staff abstractions

    master

    The waiter package uses different 'staff' abstractions depending on the type of loading indicator you want to display:

    • waiter: Ideal for displaying a spinner.
    • waitress and hostess: Designed to show progress (e.g., progress bars).
  3. The purpose of Waiter in Shiny applications

    master
    Waiter is designed to improve the perceived performance of Shiny applications. Instead of attempting to solve slow loading times through expensive hardware upgrades or complex code optimization alone, Waiter implements loading screens. By providing visual feedback during long computations or slow server responses, it reduces user uncertainty and increases patience, making the application feel more responsive and 'slicker' even if the actual processing time remains the same.
  4. Compare Waiter, Waitress, Hostess, and Attendant

    master

    The waiter package provides different components depending on your UI needs:

    FeatureWaiterWaitressHostessAttendant
    Progress Bar
    Full Screen
    Works with waiter
    Spinner
    Updatable
    Notifications
  5. Configure Waitress scope and range via selectors

    master

    The Waitress can be applied to specific elements or the entire page by providing a CSS selector during initialization.

    • Whole Page: If no selector is provided to Waitress$new(), it applies to the entire page.
    • Specific Elements: Provide a CSS selector like #plotId to target a specific element.
    • Custom Ranges: You can define a custom range for the progress bar using min and max arguments. For example, if min = 0 and max = 10, calling inc(1) will increase the progress by 10% of the total range.

    In use_waitress(), you can also customize the color of the loading bar.

    # Target a specific element with a custom range
    waitress <- Waitress$new("nav", theme = "overlay", min = 0, max = 10)
    
    # Target the whole page with a custom color in UI
    ui <- fluidPage(useWaitress(color = "#7F7FFF"))
  6. Handle waiter lifecycle events in Shiny

    master

    The waiter package fires Shiny input events when a loading screen is shown or hidden. This allows you to trigger side effects in your R server code based on the waiter's state.

    When a waiter is associated with an element id, the following input IDs are generated:

    • input$<id>_waiter_shown
    • input$<id>_waiter_hidden

    If the waiter is used in full-screen mode (not overlaying a specific element), the events are simply input$waiter_shown and input$waiter_hidden.

    # Example of observing waiter events
    server <- function(input, output){
      w <- Waiter$new(id = "plot")
    
      # ... logic to show/hide waiter ...
    
      observeEvent(input$plot_waiter_hidden, {
        print(input$plot_waiter_hidden)
      })
    
      observeEvent(input$plot_waiter_shown, {
        print(input$plot_waiter_shown)
      })
    }
  7. Use infinite loading bars with Hostess

    master

    If you cannot compute specific progress increments, use an infinite loading bar by setting infinite = TRUE in Hostess$new().

    Important: When using infinite = TRUE, you must manually call hostess$start() to begin the animation and hostess$close() when the computation ends to stop it.

    server <- function(input, output){
      hostess <- Hostess$new("loader", infinite = TRUE)
      
      hostess$start()
      
      # ... computation ...
      Sys.sleep(5)
      
      hostess$close()
      waiter_hide()
    }
  8. How to use Attendant for progress bars

    master

    The Attendant family of functions allows you to display progress bars using Bootstrap's built-in progress bars. Unlike other waiter functions, the Attendant is permanently in the DOM (though it can be hidden) rather than being an overlay. This makes it ideal for progress reporting that shouldn't block the entire UI.

    To use it, you must:

    1. Include dependencies using useAttendant() in your UI.
    2. Place attendantBar(id) in your UI where you want the bar to appear.
    3. Create an Attendant object in your server using the same id to control its state.
    ui <- fluidPage(
      useAttendant(),
      attendantBar("progress-bar")
    )
    
    server <- function(input, output){
      att <- Attendant$new("progress-bar")
    
      for(i in 1:10){
        Sys.sleep(runif(1))
        att$set(i * 10)
      }
    }
  9. Integrate waiter with shinydashboard

    master

    To use waiter in shinydashboard:

    1. Place useWaiter() inside dashboardBody().
    2. Use waiterShowOnLoad(spinner) to show a loading screen on startup.
    3. Overlaying the content section: By default, waiter might not overlay the main content area correctly because the <section> tag lacks an ID. To fix this, inject a small JavaScript snippet into tags$head to assign an ID (e.g., waiter-content) to the element with class content. Then, initialize Waiter$new("waiter-content").
    # JavaScript to add an id to the <section> tag
    add_id_to_section <- "
    $( document ).ready(function() {
      var section = document.getElementsByClassName('content');
      section[0].setAttribute('id', 'waiter-content');
    });"
    
    ui <- dashboardPage(
      dashboardHeader(),
      dashboardSidebar(),
      dashboardBody(
        tags$head(tags$script(add_id_to_section)),
        useWaiter(),
        waiterShowOnLoad(spinner)
      )
    )
    
    server <- function(input, output) {
      w <- Waiter$new("waiter-content")
      # ...
    }
  10. How to use the Waitress in Shiny

    master

    The Waitress is a reference class used to display loading bars on the entire screen or specific elements. To use it, follow these four steps:

    1. UI Setup: Place use_waitress() anywhere in your Shiny UI to include the necessary dependencies.
    2. Initialization: Set up the waitress in your server using Waitress$new(selector) or call_waitress(selector). The selector is a CSS selector (e.g., #plotId or nav) indicating where the loading bar should appear.
    3. Progression: Programmatically control the progress using the set(), inc(), and auto() methods.
    4. Cleanup: Call the close() method to hide the loading screen once the task is complete.
    library(shiny)
    library(waiter)
    
    ui <- fluidPage(
      useWaitress(),
      plotOutput("plot")
    )
    
    server <- function(input, output){
      waitress <- Waitress$new("#plot")
      
      output$plot <- renderPlot({
        waitress$start()
        # ... perform task ...
        waitress$close()
      })
    }
    
    shinyApp(ui, server)
  11. Show a loading screen on app launch with `waiterShowOnLoad`

    master

    To show a loading screen immediately when the app launches (before the Shiny session is fully established), use waiterShowOnLoad().

    Important:

    1. You must place waiterShowOnLoad() after useWaiter() in your UI.
    2. Because this is not programmatically launched by the server, you must manually call waiter_hide() in your server logic to remove it once the app is ready.
    ui <- fluidPage(
      useWaiter(), 
      waiterShowOnLoad(html = spin_fading_circles()),
      h3("Content visible after loading")
    )
    
    server <- function(input, output, session){
      Sys.sleep(3)
      waiter_hide()
    }
  12. Use Steward to animate loading backgrounds

    master

    The steward package allows you to animate the background of your loading screen.

    To use it:

    1. Include useSteward() in your Shiny UI.
    2. Use waiterShowOnLoad() to define the initial loading state.

    Example usage:

    ui <- fluidPage(
      useWaiter(), 
      useSteward(),
      h3("Content you will only see after loading screen has disappeared"),
      waiterShowOnLoad(spin_fading_circles()) 
    )
    library(shiny)
    library(waiter)
     
    ui <- fluidPage(
      useWaiter(), 
      useSteward(),
      h3("Content you will only see after loading screen has disappeared"),
      waiterShowOnLoad(spin_fading_circles()) 
    )
    
    server <- function(input, output, session){
      Sys.sleep(10) # do something that takes time
      waiter_hide()
    }
    
    shinyApp(ui, server)