英文:
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 yourinputId
in a module, even if it is server side. - you cannot name two outputs the same :
button1
for thebutton
AND theuiOutput
, 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 <- function(id){
ns <- NS(id)
column(3, uiOutput(ns("uibutton1"))),
column(3, uiOutput(ns("uibutton2")))
}
moduleServer <- function(input, output, session, rv){
ns <- session$ns # don't forget ns in server side module
observeEvent(input$button1, {
rv$btn1 <- rv$btn1 +1
})
observeEvent(input$button2, {
rv$btn2 <- rv$btn2 +1
})
# do not use the same outputId
output$uibutton1 <- renderUI({
actionButton(ns("button1"), label = "button 1") # use ns()
})
output$uibutton2 <- renderUI({
actionButton(ns("button2"), label = "button 2")
})
}
ui <- fluidPage(
moduleUI("moduleId"),
uiOutput("text")
)
server <- function(input, output, session) {
# Initialise a reactiveValues
rv_module <- reactiveValues(btn1 = 0, btn2 = 0)
callModule(moduleServer, "moduleId", rv = rv_module)
output$text <- renderUI({
paste("btn1 : ",rv_module$btn1, " | btn2 : ", rv_module$btn2)
})
}
runApp(shinyApp(ui, server))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论