shiny icon indicating copy to clipboard operation
shiny copied to clipboard

only last modal shows when multiple modals are triggered by the same event

Open ifoxfoot opened this issue 2 years ago • 3 comments

  • Edit to add that including a return statement in the loop causes modal one to pop up but not modal two.

System details

Browser Version: Chrome Version 113.0.5672.92 Output of sessionInfo():

R version 4.2.3 (2023-03-15)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Monterey 12.6.3

Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] shiny_1.7.4  cowsay_0.8.2

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.10      rmsfact_0.0.3    withr_2.5.0      digest_0.6.31    crayon_1.5.2    
 [6] later_1.3.1      mime_0.12        R6_2.5.1         jsonlite_1.8.4   lifecycle_1.0.3 
[11] xtable_1.8-4     magrittr_2.0.3   cachem_1.0.8     rlang_1.1.1      cli_3.6.1       
[16] rstudioapi_0.14  promises_1.2.0.1 jquerylib_0.1.4  bslib_0.4.2      ellipsis_0.3.2  
[21] fortunes_1.5-4   tools_4.2.3      httpuv_1.6.11    fastmap_1.1.1    compiler_4.2.3  
[26] memoise_2.0.1    htmltools_0.5.5  sass_0.4.6      

Example application or steps to reproduce the problem

click show modal. Only Warning Two shows up.

library(shiny)

mess_fun <- function() {
  message("WARNING ONE")
  message("WARNING TWO")
}

shinyApp(
  ui = basicPage(
    actionButton("show", "Show modal dialog")
  ),
  server = function(input, output) {

    observeEvent(input$show, {
      warning_list <- list()
      withCallingHandlers(
        mess_fun(),
        message=function(w) {warning_list <<- c(warning_list, list(w$message))})
      for (i in warning_list) {
        showModal(modalDialog(i)) }
    })

  }
)

Describe the problem in detail

In my code, ideally modal one should pop up, and when it is dismissed, modal two should pop up. However, only modal two pops up.

ifoxfoot avatar Jun 07 '23 19:06 ifoxfoot

Not sure it's possible like this, I don't know.

Alternatively, you could use two observers, as in the last example of ?shiny::modalDialog. Or you can use the shinyalert package, which allows to chain the alerts.

stla avatar Jun 12 '23 15:06 stla

Hi @stla yeah I'm not sure it is possible either, but yes it works using shinyalert. I suppose if it's not possible this is more of a feature request...

ifoxfoot avatar Jun 13 '23 19:06 ifoxfoot

I guess the issue here is, that shiny's modals always get the same id: "shiny-modal" (also shown here - please see the "multiple modals" edit).

However, you could re-trigger the observer after closing the first modal as long as items are in the list - something like this:

library(shiny)

mess_fun <- function() {
  message("WARNING ONE")
  message("WARNING TWO")
}

shinyApp(
  ui = basicPage(actionButton("show", "Show modal dialog")),
  server = function(input, output, session) {
    warning_list <- list() # consider using a reactiveVal instead
    withCallingHandlers(
      mess_fun(),
      message = function(w) {
        warning_list <<- c(warning_list, list(w$message))
      }
    )
    
    observeEvent(c(input$show, input$dismiss), {
      if(length(warning_list) == 0 && input$dismiss == 1) {
        removeModal()
      }
      if(length(warning_list) > 0 && (is.null(input$dismiss) || input$dismiss > 0)){
        showModal(modalDialog(warning_list[[1]], footer = actionButton("dismiss", "Dismiss")))
        warning_list[[1]] <<- NULL
      }
    }, ignoreInit = TRUE)
  }
)

PS: personally I'd show both (or multiple) warnings using the same modal instead.

ismirsehregal avatar Oct 25 '23 08:10 ismirsehregal