简体   繁体   中英

R Shiny - Setting input values with 'session$sendCustomMessage' inside a Shiny module

My app contains a button called set value . I would like to use sendCustomMessage and setInputValue to reset the value of input inp to 'hi' each time set value is clicked. I'm using a wrapper function called setInputVal for the sendCustomMessage method.

The value of inp is reset as expected if I specify the namespace prefix for the input id inside the call to setInputVal but not if I leave it out. So setInputVal(session, ns('inp'), 'hi') works but setInputVal(session, 'inp', 'hi') doesn't.

Why do I need to specify the namespace prefix here? My thinking was that the session$ bit in session$sendCustomMessage implies that the message is accessing module's session and so the namespace prefix isn't be required (similar to how in the module's server function we use input$inp to access inp 's value and not input[[ns('inp')]] ).

And why is it that when we use an update* function (like updateSelectInput ) in a module server, we don't need to specify the ns prefix? (I've included a selectInput in the UI and an observeEvent in the server to demonstrate updateSelectInput .) When I look at the code for updateSelectInput, I see that it also uses session$sendInputMessage(inputId, message) and does not seem to attach the ns prefix to the inputId parameter at any point.

library(shiny)

setInputVal <- function(session, inputId, value) {
  session$sendCustomMessage(
    type = 'setInputVal',
    message = list(
      id = inputId, value = value)
  )
}

# module UI ---------------------------------------------------------------
modUI <- function(id) {

  ns = NS(id)

  tagList(
    tags$head(tags$script("Shiny.addCustomMessageHandler('setInputVal', function(data) {
  Shiny.setInputValue(data.id, data.value);
});")),
    # selectInput(ns('letter'), 'letter', letters),
    actionButton(ns('set'), 'set value')
  )
}


# module server -----------------------------------------------------------
modServer <- function(input, output, session) {

  ns = session$ns

  observeEvent(input$set, setInputVal(session, 'inp', value = 'hi'))

  observe(print(input$inp))

  # observeEvent(input$set, {
  #   
  #   updateSelectInput(session, 'letter', selected = 'u')
  #   
  #   print(input$letter)
  # })
}


# main UI -----------------------------------------------------------------
ui <- fluidPage(modUI('hi'))


# main server -------------------------------------------------------------
server <- function(input, output, session) { 
  callModule(modServer, 'hi')
}

# Run app
shinyApp(ui, server)

With sendCustomMessage() you are just sending a JSON object to be handled in JavaScript. By the time you call Shiny.setInputValue() in JS, you've already lost all information about the session: only the message data remains. And in this case that message happens to contain an unscoped input id, meaning that you're actually setting the value for a global "inp" input. Because a custom message could literally be doing anything, there's nothing that the session can modify about it.

However, when you use sendInputMessage() the context is different: now the session knows that there is an inputId and it should be scoped, which it does automatically; see here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM