rshinymoduleshinyjs

How to namespace when using shinyjs?


I am creating namespace modules but am having problems now when using shinyjs() functions like hidden() and show(). In the below Example 1: with module, clicking the action button testButton should render a little text snippet in the UI that says "shinyjs works!", but it doesn't even though I've tried name spacing the objects. Why is this not working?

When I run the same code but without namespace modularizing such as in Example 2: no module below, the code works fine.

So I have issues with name spacing. What am I doing wrong? Please help!!

Example 1: with module

library(shiny)
library(shinyjs)

mod30_A_ui <- function(id) {
  ns <- NS(id)
  tagList(
    shinyjs::useShinyjs(),  
    actionButton("testButton", "Show Text"),  
    hidden(textOutput(ns("testText"))),  
  )
}

mod30_A_server <- function(id, mod10_data) {
  moduleServer(id, function(input, output, session) {
    
    output$testText <- renderText("shinyjs works!")
    
    observeEvent(input$testButton, {
      show(session$ns("testText"))  
    })
    
  })
}

# Remaining code is local UI and server for running as standalone module
ui <- fluidPage(
  shinyjs::useShinyjs(), 
  sidebarLayout(
    sidebarPanel(
      h2("Mod30_A Sidebar")
    ),
    mainPanel(mod30_A_ui("mod30_A"))
  )
)

server <- function(input, output, session) {
  mod10_data <- reactiveValues()
  mod30_A_server("mod30_A", mod10_data)
}

shinyApp(ui, server)

Example 2: no module

library(shiny)

ui <- fluidPage(
  shinyjs::useShinyjs(), 
  sidebarLayout(
    sidebarPanel(
      h2("Mod30_A Sidebar")
    ),
    mainPanel(
      shinyjs::useShinyjs(),  
      actionButton("testButton", "Show Text"),  
      hidden(textOutput("testText")),  
    )
  )
)

server <- function(input, output, session) {
  output$testText <- renderText("shinyjs works!")
  
  observeEvent(input$testButton, {
    show("testText")  
  })
}

shinyApp(ui, server)

Solution

  • As a rule of thumb, you should namespace (by using ns()) all the ids in the UI part of the module, while the ids in the server don't need to be namespaces (as some shiny magic will do it for you). There are of course exceptions (like generating inputs via renderUI, insertUI) but in most cases this should be sufficient.

    Try this:

    library(shiny)
    library(shinyjs)
    
    mod30_A_ui <- function(id) {
      ns <- NS(id)
      tagList(
        shinyjs::useShinyjs(),
        actionButton(ns("testButton"), "Show Text"),
        hidden(textOutput(ns("testText"))),
      )
    }
    
    mod30_A_server <- function(id, mod10_data) {
      moduleServer(id, function(input, output, session) {
    
        output$testText <- renderText("shinyjs works!")
    
        observeEvent(input$testButton, {
          show("testText")
        })
    
      })
    }
    
    # Remaining code is local UI and server for running as standalone module
    ui <- fluidPage(
      shinyjs::useShinyjs(),
      sidebarLayout(
        sidebarPanel(
          h2("Mod30_A Sidebar")
        ),
        mainPanel(mod30_A_ui("mod30_A"))
      )
    )
    
    server <- function(input, output, session) {
      mod10_data <- reactiveValues()
      mod30_A_server("mod30_A", mod10_data)
    }
    
    shinyApp(ui, server)
    

    What I've done is simply namespace the ids (both output and input ids) in the UI and remove the namespacing in the server.