2

sorry if this is a simple question, but I am quite new to Shiny and even newer to using Modules.

I have a larger application in which one of its pages I use a button to open a Shiny Modal, there are quite a few things going on in this modal, so I made a separate server for it. Inside the modal server are some observeEvent handlers. The problem arises when the user tries to use the modal more than once, as, apparently, opening the modal a second time creates a second instance of its server and then the observeEvents trigger multiple times.

I know that if I use different IDs for the server I can solve this, but I would really like to keep the same ID. In my head, I thought creating a server with the same ID would replace the previous one, but that doesn't seem to be the case. Maybe I just need to delete the previous server when the modal closes(?), I am not sure. Anyway, any help is appreciated.

Here is a reproducible example that shows this behaviour:

Opening the modal a second time and clicking the button makes multiple notifications appear.


modal_server <- function(id){
  moduleServer(id,
               function(input, output, session){
                 
                 ns <- session$ns
                 
                 showModal(modalDialog(actionButton(ns("show_notification"), "Show Notification")))
                 
                 observeEvent(input$show_notification, {
                   showNotification("hi")
                 })
               })
}

ui <- fluidPage(
  actionButton("show_modal", "Show Modal")
)

server <- function(input, output, session) {
  observeEvent(input$show_modal, {
    modal_server(id = "modal")
  })
  
}

shinyApp(ui = ui, server = server)
aaa
  • 63
  • 3

1 Answers1

1

One option to fix your issue would be to move the UI code to the module too and use two observeEvents inside the module server to handle the two events, i.e. showing the modal and showing the notification:

library(shiny)

modal_ui <- function(id) {
  ns <- NS(id)

  actionButton(ns("show_modal"), "Show Modal")
}

modal_server <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      ns <- NS(id)

      observeEvent(input$show_modal, {
        showModal({
          modalDialog(
            actionButton(ns("show_notification"), "Show Notification")
          )
        })
      })

      observeEvent(input$show_notification, {
        showNotification("hi")
      })
    }
  )
}

ui <- fluidPage(
  modal_ui("modal")
)

server <- function(input, output, session) {
  modal_server(id = "modal")
}

shinyApp(ui = ui, server = server)
stefan
  • 90,330
  • 6
  • 25
  • 51
  • This is a nice workaround, but it still seems like the problem is calling the module twice with the same ID, do you know of any sources or examples that deal with this kind of problem? – aaa Sep 05 '22 at 16:24
  • Wouldn't call it a workaround. IMHO this is the natural way to set up a module. (; Also I don't understand what you mean by "problem is calling the module twice with the same ID". The module is called only once and creates only one modal. The server part than takes care of the events. And as far as I get it, doing so avoids the issue you mentioned in your post. – stefan Sep 05 '22 at 22:10