【问题标题】:R Shiny - Setting input values with 'session$sendCustomMessage' inside a Shiny moduleR Shiny - 在 Shiny 模块中使用“session$sendCustomMessage”设置输入值
【发布时间】:2020-03-19 05:38:08
【问题描述】:

我的应用程序包含一个名为 set value 的按钮。每次单击set value 时,我想使用sendCustomMessagesetInputValue 将输入inp 的值重置为“hi”。我正在为sendCustomMessage 方法使用一个名为setInputVal 的包装函数。

如果我在 setInputVal 调用中为输入 id 指定命名空间前缀,inp 的值会按预期重置,但如果我将其忽略则不会。所以setInputVal(session, ns('inp'), 'hi') 有效,但setInputVal(session, 'inp', 'hi') 无效。

为什么我需要在这里指定命名空间前缀? 我的想法是session$sendCustomMessage 中的session$ 位意味着消息正在访问模块的会话,因此命名空间前缀不是是必需的(类似于在模块的服务器函数中我们使用input$inp 访问inp 的值而不是input[[ns('inp')]])。

为什么我们在模块服务器中使用update*函数(如updateSelectInput)时,不需要指定ns前缀?(我已经包含UI 中的 selectInput 和服务器中的 observeEvent 演示 updateSelectInput。)当我查看 updateSelectInput 的代码时,我发现它也使用了 session$sendInputMessage(inputId, message) 并且似乎没有将 ns 前缀附加到 inputId参数。

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)

【问题讨论】:

  • useShinyUtils() 来自哪里?
  • 对不起,这是一个错字,我现在已经更正了。

标签: r shiny


【解决方案1】:

使用sendCustomMessage(),您只是发送一个 JSON 对象以在 JavaScript 中处理。当您在 JS 中调用 Shiny.setInputValue() 时,您已经丢失了有关会话的所有信息:只剩下消息数据。在这种情况下,该消息恰好包含一个无范围的输入 id,这意味着您实际上是在为全局 "inp" 输入设置值。因为自定义消息实际上可以做任何事情,所以会话无法修改它。

但是,当您使用 sendInputMessage() 时,上下文有所不同:现在会话知道有一个 inputId 并且它应该是作用域的,它会自动执行;见here

【讨论】:

  • 谢谢,我没有注意到它使用的是sendInputMessage 而不是sendCustomMessage。而且我只能将sendInputMessage 用于DOM 中存在的输入?它似乎对我的应用程序中的输入没有任何作用,因为 UI 中不存在该输入。
  • @user51462 是的,我在测试时也注意到了这一点。我认为这是因为如果输入在 DOM 中不存在,Shiny 对此一无所知。例如,没有任何信息表明该输入应该是文本输入。我怀疑这种情况与a custom input object 非常相似,因此可能需要一些手动输入绑定?但我不确定。
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 2018-12-06
  • 2016-09-06
  • 1970-01-01
  • 2017-01-03
  • 2020-09-16
  • 2014-04-01
  • 2018-02-13
相关资源
最近更新 更多