6

I want to be able to switch various parts of my UI on/off using shinyjs show and hide. I need to access parts of the UI outside the module from within a module. Is this possible?

See the attached app code. The show/hide buttons in the main server code work, but those in the module do not.

Thanks for any suggestions.

exampleUI <- function(id) {
            ns <- NS(id)
            tagList(actionButton(ns("hide_id"), "Module - Hide divs"),
                    actionButton(ns("show_id"), "Module - Show divs"),
                    uiOutput(ns("plot_id")))
    }
    
    shinyUI(fluidPage(
            shinyjs::useShinyjs(),
                    shinyjs::hidden(tags$div(id = "hidden", "hidden")),
                    tags$div(id = "shown", "shown"),
                    actionButton("hide_id", "Hide divs"),
                    actionButton("show_id", "Show divs"),
                    exampleUI("eg")))

    example <- function(input, output, session)
    {
        ns <- session$ns
        
        observeEvent(input$hide_id,
        {
            shinyjs::hide("hidden")
            shinyjs::hide("shown")
        })
        observeEvent(input$show_id,
        {
            shinyjs::show("hidden")
            shinyjs::show("shown")
        })
    }
    
    shinyServer(function(input, output) {
    
        callModule(example, "eg")
        observeEvent(input$hide_id,
        {
            shinyjs::hide("hidden")
            shinyjs::hide("shown")
        })
        observeEvent(input$show_id,
        {
            shinyjs::show("hidden")
            shinyjs::show("shown")
        })
    })
Jan
  • 4,974
  • 3
  • 26
  • 43
jxf
  • 163
  • 1
  • 9

1 Answers1

1

That wasn't possible until release v1.1 (January, 2020) came out. With that release the parameter asis was introduced. I quote:

When asis=TRUE, the ID will not be namespaced when inside a module.

Here is adapted reprex of the askers code that shows how it works:

library(shiny)
library(shinyjs)

exampleUI <- function(id) {
  ns <- NS(id)
  tagList(actionButton(ns("hide_id"), "Module - Hide divs"),
          actionButton(ns("show_id"), "Module - Show divs"),
          uiOutput(ns("plot_id")))
}


example <- function(input, output, session)
{
  ns <- session$ns
  
  observeEvent(input$hide_id, {
                 shinyjs::hide("hidden", asis = TRUE)
                 shinyjs::hide("shown", asis = TRUE)
                 shinyjs::hide("plot_id")
               })
  observeEvent(input$show_id, {
                 shinyjs::show("hidden", asis = TRUE)
                 shinyjs::show("shown", asis = TRUE)
                 shinyjs::show("plot_id")
               })
  output$plot_id <- renderUI({
    "This is the module calling ..."
  })
}

UI <- function() {
  fluidPage(
    shinyjs::useShinyjs(),
    shinyjs::hidden(tags$div(id = "hidden", "hidden")),
    tags$div(id = "shown", "shown"),
    actionButton("hide_id", "Hide divs"),
    actionButton("show_id", "Show divs"),
    exampleUI("eg"))
}

server <- function(input, output, session) {
  
  callModule(example, "eg")
  observeEvent(input$hide_id, {
                 shinyjs::hide("hidden")
                 shinyjs::hide("shown")
               })
  observeEvent(input$show_id, {
                 shinyjs::show("hidden")
                 shinyjs::show("shown")
               })
}

shinyApp(UI, server)
Jan
  • 4,974
  • 3
  • 26
  • 43
  • Where is the `moduleServer()` for `exampleUI` ? – kraggle Oct 17 '22 at 20:52
  • Thank you for pointing this out. The function `example()` provides the server. But it is not a textbook implementation (at least not to recent releases of Shiny). The textbook samples usually use `moduleServer()` inside the server module function. In a productive environment this function does merely call `callModule()`. Since this sample calls `callModule()` explicitely in the app it works anyway. Only if you want to run the module in a `MockShinySession` you would need to rework it and adapt it to more recent releases of Shiny modules. – Jan Oct 20 '22 at 06:31