Adding wrappers to a shiny module to enable an ease of dynamically adding and removing modules within a shiny application.

makeModuleUIDestroyable(module_fn, wrapper = shiny::div)

makeModuleServerDestroyable(module_fn)

Arguments

module_fn

The server-side part of the module

wrapper

If the module is a `shiny::tagList()`, then an HTML tag will be wrapped by an HTML tag so that a shiny.destroy attribute can be attached

Value

An updated function call of `module_fn`.

For the UI, if the returned object from `module_fn` is a `shiny.tag` then an additional attribute will be added to the top-level HTML tag for {shiny.destroy} to reference when removing the UI. If the returned object is a `shiny.tag.list` then a wrapper tag will surround the module with the attribute to destroy the module.

For the server, each observer will be assigned to the `.shiny.destroy` list within `session$userData`. The returned object from the module remains the same as before.

Examples

library(shiny)

# UI
basicModuleUI <- function(id) {
  ns <- NS(id)
  actionButton("click", "Increase")
}

destroyableModuleUI <- makeModuleUIDestroyable(basicModuleUI)

# Server-side
basicMoudleServer <- function(id) {
  moduleServer(id, function(input, output, session) {
    rv <- reactiveVal()
    observeEvent(input$click, rv(input$click))
  })
}

destroyableModuleServer <- makeModuleServerDestroyable(basicMoudleServer)

# Shiny Application
ui <- fluidPage(
  destroyableModuleUI(id = "test"),
  actionButton("destroy", "Destroy module"),
  textOutput("reactive_value")
)

server <- function(input, output, session) {
  top_rv <- reactiveVal()

  reactive_value <- destroyableModuleServer("test")
  observeEvent(reactive_value(), top_rv(reactive_value()))

  output$reactive_value <- renderText(top_rv())

  observeEvent(input$destroy, destroyModule("test"))
}