Home > Mobile >  Why `insertUI` is not working as an alternative for module UI?
Why `insertUI` is not working as an alternative for module UI?

Time:03-06

I have tried to use insertUI as an alternative for explicitly using module UI in the UI part of Shiny app, but without the success. How should I use insertUI in my example to get the desired effect, i.e. to be able to display modalDialog?

This doesn't work (using insertUI instead of explicitly using module in UI part of app):

library(shiny)
library(magrittr)

modUI <- function(id) {
  ns <- NS(id)
  key_pressed <- ns("key_pressed")
  js <- glue::glue_safe('
    document.addEventListener("keydown", function(e) {{
     Shiny.setInputValue("{key_pressed}", e.key, {{priority: "event"}});
    }});
  ')
  singleton(tags$script(htmltools::HTML(js)))
}

modServer <- function(keyEvent = "F1",
                                  id) {
  
  insertUI("head", "beforeEnd", modUI("test"), immediate = TRUE)
  
  moduleServer(
    id,
    function(input, output, session) {
      observe({
        req(input$key_pressed == keyEvent)
        showModal(modalDialog())
      }) %>% 
        bindEvent(input$key_pressed)
    }
  )
}

ui <- fluidPage(
  #modUI("test")
)

server <- function(input, output, session) {
  modServer(id = "test")
}

shinyApp(ui, server)

This works (using module explicitly in the UI part of app):

library(shiny)
library(magrittr)

modUI <- function(id) {
  ns <- NS(id)
  key_pressed <- ns("key_pressed")
  js <- glue::glue_safe('
    document.addEventListener("keydown", function(e) {{
     Shiny.setInputValue("{key_pressed}", e.key, {{priority: "event"}});
    }});
  ')
  singleton(tags$script(htmltools::HTML(js)))
}

modServer <- function(keyEvent = "F1",
                                  id) {
  
  #insertUI("head", "beforeEnd", modUI("test"), immediate = TRUE)
  
  moduleServer(
    id,
    function(input, output, session) {
      observe({
        req(input$key_pressed == keyEvent)
        showModal(modalDialog())
      }) %>% 
        bindEvent(input$key_pressed)
    }
  )
}

ui <- fluidPage(
  modUI("test")
)

server <- function(input, output, session) {
  modServer(id = "test")
}

shinyApp(ui, server)

The code above adds JS code to add keydown listener - modalDialog will be displayed after pressing F1.

CodePudding user response:

A search in the Shiny GitHub repository reveals that this is an open issue with Shiny: inserted script tags aren't executed unless wrapped in tags$head(). So, meanwhile, you could wrap the script tag in your module UI in tags$head() to get this to work:

script <- tags$script(htmltools::HTML(js))
singleton(tags$head(script))
  • Related