R Shiny模块 – 模块向主服务器返回多个reactiveVals

huangapple go评论65阅读模式
英文:

R Shiny Modules - module return multiple reactiveVals to main server

问题

I have problem with communication between main server and server module. I would like to return from module current reactiveVals and then use them in main app.
我遇到了主服务器与服务器模块之间的通信问题。我想从模块中返回当前的reactiveVals并在主应用程序中使用它们。

I created basic app which shows my problem. Module contains 2 buttons and 2 reactiveVals, each of them contains the number of clicks on the corresponding button.
我创建了一个基本的应用程序来展示我的问题。模块包含2个按钮和2个reactiveVals,每个reactiveVal都包含相应按钮的点击次数。

In the main server, I would like to know which value has changed and react to this change with some action (in the example, a change in the returned text).
在主服务器中,我想知道哪个值发生了变化,并对此变化采取一些操作(例如,在返回的文本中进行更改)。

Unfortunately, the code below returns values from the module only at the time of its launch, then, if there are changes inside the module that we are interested in, I am not informed about it.
不幸的是,下面的代码仅在模块启动时返回模块中的值,然后,如果模块内发生了我们感兴趣的更改,我将不会收到通知。

How should I modify the code below to get the effect I am interested in?
我应该如何修改下面的代码以获得我感兴趣的效果?

英文:

I have problem with communication between main server and server module. I would like to return from module current reactiveVals and then use them in main app.
I created basic app which shows my problem. Module contains 2 buttons and 2 reactiveVals, each of them contains the number of clicks on the corresponding button.
in the main server, I would like to know which value has changed and react to this change with some action (in the example, a change in the returned text).
unfortunately, the code below returns values from the module only at the time of its launch, then, if there are changes inside the module that we are interested in, I am not informed about it.

How should I modify the code below to get the effect I am interested in?

library(shiny)

moduleUI <- function(id){
  ns <- NS(id)
  wellPanel(
    fluidRow(
      column(3, uiOutput(ns("button1"))),
      column(3, uiOutput(ns("button2")))
    )
  )
}

moduleServer <- function(input, output, session){
  rv_button1 <- reactiveVal(0)
  rv_button2 <- reactiveVal(0)
  
  observeEvent(input$button1, {
    rv_button1(rv_button1()+1)
    print(rv_button1())
  })
  observeEvent(input$button2, {
    rv_button2(rv_button2()+1)
    print(rv_button2())
    
  })
  
  output$button1 <- renderUI({
    actionButton("button1", label = "button 1")
  })
  output$button2 <- renderUI({
    actionButton("button2", label = "button 2")
  })
  
  return(
    list(
      button1 = rv_button1,
      button2 = rv_button2
    )
  )
}

ui <- fluidPage(
  moduleUI("moduleId"),
  fluidRow(uiOutput("text"))
)

server <- function(input, output, session) {
  rv_module <- reactiveVal(
    list(
      button1 = 0, 
      button2 = 0
    )
  )
  rv_text <- reactiveVal("")
  
  rv_module <- callModule(moduleServer, "moduleId")

  observeEvent(rv_module$button1, {
    rv_text("Button 1 was clicked")
  })
  observeEvent(rv_module$button2, {
    rv_text("Button 2 was clicked")
  })
  
  output$text <- renderUI({
    HTML(rv_text())
  })
}

runApp(shinyApp(ui, server))

答案1

得分: 2

Here is the translated code:

首先需要注意以下几点:
 - 即使在服务器端,你需要在模块的 `inputId` 中添加 `ns()`。
 - 你不能给两个输出起相同的名称:`button1` 同时用于 `button` 和 `uiOutput`,这样不会起作用。

接下来,为了在服务器和模块之间,或者在多个模块之间进行通信,最简单的方法是将 `reactiveValues` 作为模块的参数传递。

```R
library(shiny)

moduleUI <- function(id){
  ns <- NS(id)
  fluidRow(
    column(3, uiOutput(ns("uibutton1"))),
    column(3, uiOutput(ns("uibutton2")))
  )
}

moduleServer <- function(input, output, session, rv){
  ns <- session$ns # 不要忘记在服务器端模块中使用 ns
  observeEvent(input$button1, {
    rv$btn1 <- rv$btn1 + 1
  })
  observeEvent(input$button2, {
    rv$btn2 <- rv$btn2 + 1
  })
  
  # 不要使用相同的 outputId 
  output$uibutton1 <- renderUI({
    actionButton(ns("button1"), label = "按钮 1") # 使用 ns()
  })
  output$uibutton2 <- renderUI({
    actionButton(ns("button2"), label = "按钮 2")
  })
}

ui <- fluidPage(
  moduleUI("moduleId"),
  uiOutput("text")
)

server <- function(input, output, session) {
  # 初始化一个 reactiveValues
  rv_module <- reactiveValues(btn1 = 0, btn2 = 0)

  callModule(moduleServer, "moduleId", rv = rv_module)
  
  output$text <- renderUI({
    paste("按钮 1:", rv_module$btn1, " | 按钮 2:", rv_module$btn2)
  })
}

shinyApp(ui, server)

请注意,我已经将代码中的中文翻译添加到注释中,以便你更好地理解。

英文:

Few things first :

  • you need to add ns() to your inputId in a module, even if it is server side.
  • you cannot name two outputs the same : button1 for the button AND the uiOutput, it won't work.

Then, to communicate between server and module, or between several module, the easiest way is to pass a reactiveValues as a parameter of your module.

library(shiny)

moduleUI &lt;- function(id){
  ns &lt;- NS(id)
    column(3, uiOutput(ns(&quot;uibutton1&quot;))),
    column(3, uiOutput(ns(&quot;uibutton2&quot;)))
}

moduleServer &lt;- function(input, output, session, rv){
  ns &lt;- session$ns # don&#39;t forget ns in server side module
  observeEvent(input$button1, {
    rv$btn1 &lt;- rv$btn1 +1
  })
  observeEvent(input$button2, {
    rv$btn2 &lt;- rv$btn2 +1
  })
  
  # do not use the same outputId 
  output$uibutton1 &lt;- renderUI({
    actionButton(ns(&quot;button1&quot;), label = &quot;button 1&quot;) # use ns()
  })
  output$uibutton2 &lt;- renderUI({
    actionButton(ns(&quot;button2&quot;), label = &quot;button 2&quot;)
  })
}

ui &lt;- fluidPage(
  moduleUI(&quot;moduleId&quot;),
  uiOutput(&quot;text&quot;)
)

server &lt;- function(input, output, session) {
  # Initialise a reactiveValues
  rv_module &lt;- reactiveValues(btn1 = 0, btn2 = 0)

  callModule(moduleServer, &quot;moduleId&quot;, rv = rv_module)
  
  output$text &lt;- renderUI({
    paste(&quot;btn1 : &quot;,rv_module$btn1, &quot; | btn2 : &quot;, rv_module$btn2)
  })
}

runApp(shinyApp(ui, server))

huangapple
  • 本文由 发表于 2023年5月10日 18:08:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76217171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定