JohnCoene / waiter

🕰️ Loading screens for Shiny
https://waiter.john-coene.com/
Other
495 stars 25 forks source link

fix: Autowaiter bug when called multiple times #140

Closed federiva closed 11 months ago

federiva commented 11 months ago

Closes #139

Thanks for this awesome package!

Changes in this PR

In the previous implementation the variable auto was being declared in the global scope. This was causing that multiple calls to the autoWaiter function were attempting to redeclare the function thus the error message mentioned by @daattali: Uncaught SyntaxError: Identifier 'auto' has already been declared

By declaring the auto variable within the scope of the callback when listening to shiny:recalculating we avoid this problem

How to test

Here we have an example shiny app (see below) that uses two modules with autoWaiter pointing to an specific id. In this example you'll see that the first autowaiter called will work as expected while the second one won't (see gif) Peek 2023-09-22 13-35

With the changes in this PR looks like this Peek 2023-09-22 13-36

Example app

library(shiny)
library(waiter)

# Define Module A
module_a_ui <- function(id) {
  ns <- NS(id)
  fluidPage(
    autoWaiter(id = ns("plot")),
    sidebarLayout(
      sidebarPanel(
        actionButton(ns("btn_submit"), "Plot")
      ),
      mainPanel(
        plotOutput(ns("plot"))
      )
    )
  )
}

module_a_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$btn_submit, {
      output$plot <- renderPlot({
        Sys.sleep(1)
        plot(iris)
      })
    })
  })
}

# Define Module B
module_b_ui <- function(id) {
  ns <- NS(id)
  fluidPage(
    autoWaiter(id = ns("plot")),
    sidebarLayout(
      sidebarPanel(
        actionButton(ns("btn_submit"), "Plot")
      ),
      mainPanel(
        plotOutput(ns("plot"))
      )
    )
  )
}

module_b_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$btn_submit, {
      output$plot <- renderPlot({
        Sys.sleep(1)
        plot(iris)
      })
    })
  })
}

# Main Shiny App
ui <- fluidPage(
  tabsetPanel(
    tabPanel("Module A", module_a_ui("moduleA")),
    tabPanel("Module B", module_b_ui("moduleB"))
  )
)

server <- function(input, output, session) {
  module_a_server("moduleA")
  module_b_server("moduleB")
}

shinyApp(ui, server)
JohnCoene commented 11 months ago

Thank you!