javascriptrshinyshinyjs

How do I use shinjs::extendShinyjs() in a shiny module?


shinyjs::extendShinyjs() does not seem to work in a Shiny module without at least some namespacing.

Here is an example of using a simple JS extension to increase an input value (which works as intended):

library(shiny)

ui <-  tagList(
  fluidPage(
    shinyjs::useShinyjs(),
    shinyjs::extendShinyjs(text = "shinyjs.increase_click_count = function(val){
        Shiny.setInputValue('count', +val + 1, { priority: 'event' })
      }", functions = "increase_click_count"
    ),
    actionButton("increase","Increase"),
    numericInput("count", "Count", 0),
    textOutput("clicks")
  )
)


server <- function(input, output, session) {
    observeEvent(input$increase, {
    shinyjs::js$increase_click_count(input$count)
  })

  output$clicks = renderText(input$count)
}

shinyApp(ui, server)

However, when I wrap this logic in a module, the shinyjs.increase_click_count() function no longer updates the value:

library(shiny)

module_ui <- function(id) {
  tagList(
    shinyjs::useShinyjs(),
    shinyjs::extendShinyjs(text = paste0("shinyjs.increase_click_count = function(val){
        Shiny.setInputValue('", NS(id, "count"), "', +val + 1, { priority: 'event' })
      }"), functions = "increase_click_count"
    ),
    actionButton("increase","Increase"),
    numericInput(NS(id, "count"), "Count", 0),
    textOutput(NS(id,"clicks"))
  )
}

module_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$increase, {
      shinyjs::js$increase_click_count(input$count)
    })
    
    output$clicks = renderText(input$count)
  })
}

ui <-  fluidPage(
  module_ui("mod")
)

server <- function(input, output, session) {
  module_server("mod")
}

shinyApp(ui, server)

How do I properly deal with Shiny module namespaces in Javascript?


Solution

  • You're missing a a NS call

    library(shiny)
    
    module_ui <- function(id) {
      tagList(
        shinyjs::useShinyjs(),
        shinyjs::extendShinyjs(text = paste0("shinyjs.increase_click_count = function(val){
            Shiny.setInputValue('", NS(id, "count"), "', +val + 1, { priority: 'event' })
          }"), functions = "increase_click_count"
        ),
        actionButton(NS(id, "increase"), "Increase"),
        numericInput(NS(id, "count"), "Count", 0),
        textOutput(NS(id,"clicks"))
      )
    }
    
    module_server <- function(id) {
      moduleServer(id, function(input, output, session) {
        observeEvent(input$increase, {
          shinyjs::js$increase_click_count(input$count)
        })
        
        output$clicks = renderText(input$count)
      })
    }
    
    ui <-  fluidPage(
      module_ui("mod")
    )
    
    server <- function(input, output, session) {
      module_server("mod")
    }
    
    shinyApp(ui, server)