Search code examples
javascriptshinyshinyjsshinymodules

How to use shiny.setInputValue within a module?


I am using the shinyjs::runjs("Shiny.setInputValue(...)) command to get the innerText value of the 'calendar_renderRange' span of the toastui calendar widget. The command is working in a non modularized app context but not in a modularized app context. See the code below.

App without a module:

library(shinyjs)
library(lubridate)
library(shiny)


ui <- basicPage(
  useShinyjs(),  
  dateRangeInput(
    "calendar_daterange",
    label = "Data Range",
    start = lubridate::today(),
    end = lubridate::today() %m+% period("1 month"),
    startview = "year"
  ),
  toastui::calendarOutput("calendar"),
  textOutput("tag")
)

server <- function(input, output){

  output$calendar <- toastui::renderCalendar(toastui::calendar(view = 'month',
                                                               navigation = TRUE))
  
  observeEvent(c(input[["calendar_renderRange"]], input[["calendar_prev"]], input[["calendar_next"]], input[["calendar_daterange"]]),{
    shinyjs::runjs("Shiny.setInputValue('calendar_renderRange', calendar_renderRange.innerText);")
  })
  
  output$tag <- renderPrint({
    req(input[["calendar_renderRange"]])
    print(input$calendar_renderRange)
  })
  
}
shinyApp(ui, server)

Same App with a module:

library(shiny)
library(lubridate)
library(shinyjs)

tableUI <- function(id) {
  ns <- NS(id)
  tagList(
    dateRangeInput(
      ns("calendar_daterange"),
      label = "Data Range",
      start = lubridate::today(),
      end = lubridate::today() %m+% period("1 month"),
      startview = "year"
    ),
    toastui::calendarOutput(ns("calendar")),
    textOutput(ns("tag2"))
  )
}

tableServer <- function(id) {
  moduleServer(id, function(input, output, session) {
  
    output$calendar <- toastui::renderCalendar(toastui::calendar(view = 'month',
                                                                 navigation = TRUE))
    
    observeEvent(c(input[["calendar_renderRange"]], input[["table1-calendar_prev"]], input[["table1-calendar_next"]], input[["calendar_daterange"]]),{
      print('okkk')
      shinyjs::runjs("Shiny.setInputValue('calendar_renderRange', table1-calendar_renderRange.innerText);")
    })

    output$tag2 <- renderPrint({
      print(input[['calendar_renderRange']])
    })
  })
}

ui <- basicPage(
  useShinyjs(),
  tableUI("table1")
)

server <- function(input, output) {
  tableServer("table1")
}

shinyApp(ui, server)


Here are the solutions I've tried but none are working:

shinyjs::runjs(sprintf('Shiny.setInputValue("%s", table1-calendar_renderRange.innerText);', session$ns("calendar_renderRange")))

shinyjs::runjs(sprintf('Shiny.setInputValue("%s", calendar_renderRange.innerText);', session$ns("calendar_renderRange")))

JS(sprintf('Shiny.setInputValue("%s", calendar_renderRange.innerText);', session$ns("calendar_renderRange")))


Solution

  • You could use the JS getElementById function to get the input ID. Here is a way of how you could define the shiny module server.

    Reference: To reference an input id via setInputValue in a modular app that uses namespaces, simply add the namespace id in front of the input id, separated by a dash: Shiny.setInputValue in modular app with namespaces

    moduleServer(id, function(input, output, session) {
        
        output$calendar <- toastui::renderCalendar(toastui::calendar(view = 'month',
                                                                     navigation = TRUE))
        
        observeEvent(c(input[["Date_du_calendrier"]], input[["calendar_prev"]], input[["calendar_next"]]),{
          print('osbv')
          shinyjs::runjs(
            paste0(
              "Shiny.setInputValue('",id,"-Date_du_calendrier', document.getElementById('",id,"-calendar_renderRange').innerText);"
            )
          )
        })
        
        output$tag2 <- renderPrint({
          print(input[["Date_du_calendrier"]])
        })
      }