在另一个模块中使用来自一个 Shiny 模块的变量值
Using variable value from one Shiny module in another module
我有三个模块:
- 第一个模块创建一个
numericInput
,其值等于 1。
- 第二个模块创建了一个
textInput
,它是在服务器函数中用renderUI
创建的。该值等于第一个模块的值+1。
- 第三个模块应该和第二个模块做同样的事情,但是值等于第二个模块的值+1。
第二个和第三个模块中textInput
和renderUI
的选择是经过深思熟虑的。该代码在没有第三个模块的情况下工作,但在包含第三个模块时抛出以下错误:Error in $: object of type 'closure' is not subsettable
。下面是最小的示例代码。非常感谢您的帮助!
first_module.R
#Define ui
first_module_ui <- function(id) {
ns <- NS(id)
tagList(numericInput(
inputId = ns("first_input"),
label = "First input:",
value = 1
))
}
#Define server logic
first_module_server <- function(input, output, session) {
return(input)
}
second_module.R
#Define ui
second_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("second_input")))
}
#Define server logic
second_module_server <- function(input, output, session, first_module_res) {
ns <- session$ns
observe({
second_input <- first_module_res$first_input + 1
output$second_input <- renderUI({
disabled(textInput(
inputId = ns("second_input"),
label = "Second input:",
value = second_input
))
})
})
return(reactive({second_input}))
}
third_module.R
#Define ui
third_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("third_input")))
}
#Define server logic
third_module_server <- function(input, output, session, second_module_res) {
ns <- session$ns
observe({
third_input <- second_module_res$second_input + 1
output$third_input <- renderUI({
disabled(textInput(
inputId = ns("third_input"),
label = "Third input:",
value = third_input
))
})
})
}
app.R
library(shiny)
library(shinyjs)
# Define UI
ui <- fluidPage(
useShinyjs(),
# Application title
titlePanel("Demo"),
# Sidebar
sidebarLayout(
sidebarPanel(
first_module_ui("first")
),
mainPanel(
second_module_ui("second"),
third_module_ui("third")
)
)
)
# Define server logic
server <- function(input, output, session) {
callModule(first_module_server, "first")
first_module_res <- callModule(first_module_server, "first")
callModule(second_module_server, "second", first_module_res)
second_module_res <- callModule(second_module_server, "second", first_module_res)
callModule(third_module_server, "third", second_module_res)
}
# Run the application
shinyApp(ui = ui, server = server)
您的代码有一些问题:
- 您不需要
observe
,您可以使用 reactive
,因为您感兴趣的是 return 值(参见 here)
- 您应该将计算值设为反应式
- 你不需要调用一个模块两次
您的代码无法正常工作,因为您 return 来自模块服务器函数的值。从第一个模块,你 return 完整的 input
这允许你在第二个模块中访问第一个模块的 input
中的值,就像你在没有任何模块的情况下访问它一样server
来自主应用程序的功能。这意味着您不需要括号来评估反应式,您可以像使用 input$first_input
.
一样执行 first_module_res$first_input
但是,第二个模块不是 return input
,而是您创建的反应式(通过 return 值中的 reactive({})
)。这现在成为输入到第三个模块的值,需要用括号计算:second_module_res()
。另请注意,您直接评估反应式,因为它是唯一的 returned 值(而不是第二个模块的完整 input
)。
library(shiny)
library(shinyjs)
#Define ui
first_module_ui <- function(id) {
ns <- NS(id)
tagList(numericInput(
inputId = ns("first_input"),
label = "First input:",
value = 1
))
}
#Define server logic
first_module_server <- function(input, output, session) {
return(input)
}
#Define ui
second_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("second_input")))
}
#Define server logic
second_module_server <- function(input, output, session, first_module_res) {
ns <- session$ns
second_input <- reactive({
first_module_res$first_input + 1
})
output$second_input <- renderUI({
disabled(textInput(
inputId = ns("second_input"),
label = "Second input:",
value = second_input()
))
})
return(reactive({second_input()}))
}
#Define ui
third_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("third_input")))
}
#Define server logic
third_module_server <- function(input, output, session, second_module_res) {
ns <- session$ns
third_input <- reactive({
second_module_res() + 1
})
output$third_input <- renderUI({
disabled(textInput(
inputId = ns("third_input"),
label = "Third input:",
value = third_input()
))
})
}
# Define UI
ui <- fluidPage(
useShinyjs(),
# Application title
titlePanel("Demo"),
# Sidebar
sidebarLayout(
sidebarPanel(
first_module_ui("first")
),
mainPanel(
second_module_ui("second"),
third_module_ui("third")
)
)
)
# Define server logic
server <- function(input, output, session) {
first_module_res <- callModule(first_module_server, "first")
second_module_res <- callModule(second_module_server, "second", first_module_res)
callModule(third_module_server, "third", second_module_res)
}
# Run the application
shinyApp(ui = ui, server = server)
编辑
您可以 return 来自具有多个反应的模块的列表:
library(shiny)
library(shinyjs)
#Define ui
first_module_ui <- function(id) {
ns <- NS(id)
tagList(numericInput(
inputId = ns("first_input"),
label = "First input:",
value = 1
))
}
#Define server logic
first_module_server <- function(input, output, session) {
return(input)
}
#Define ui
second_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("second_input")),
numericInput(
inputId = ns("additional_input"),
label = "Additional input",
value = 5
))
}
#Define server logic
second_module_server <- function(input, output, session, first_module_res) {
ns <- session$ns
second_input <- reactive({
first_module_res$first_input + 1
})
output$second_input <- renderUI({
disabled(textInput(
inputId = ns("second_input"),
label = "Second input:",
value = second_input()
))
})
return(list(
second_input = reactive({second_input()}),
additional_input = reactive({input$additional_input})
))
}
#Define ui
third_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("third_input")),
verbatimTextOutput(outputId = ns("fourth_output")))
}
#Define server logic
third_module_server <- function(input, output, session, second_module_res) {
ns <- session$ns
third_input <- reactive({
second_module_res$second_input() + 1
})
output$third_input <- renderUI({
disabled(textInput(
inputId = ns("third_input"),
label = "Third input:",
value = third_input()
))
})
output$fourth_output <- renderPrint({
second_module_res$additional_input()
})
}
# Define UI
ui <- fluidPage(
useShinyjs(),
# Application title
titlePanel("Demo"),
# Sidebar
sidebarLayout(
sidebarPanel(
first_module_ui("first")
),
mainPanel(
second_module_ui("second"),
third_module_ui("third")
)
)
)
# Define server logic
server <- function(input, output, session) {
first_module_res <- callModule(first_module_server, "first")
second_module_res <- callModule(second_module_server, "second", first_module_res)
callModule(third_module_server, "third", second_module_res)
}
# Run the application
shinyApp(ui = ui, server = server)
我有三个模块:
- 第一个模块创建一个
numericInput
,其值等于 1。 - 第二个模块创建了一个
textInput
,它是在服务器函数中用renderUI
创建的。该值等于第一个模块的值+1。 - 第三个模块应该和第二个模块做同样的事情,但是值等于第二个模块的值+1。
第二个和第三个模块中textInput
和renderUI
的选择是经过深思熟虑的。该代码在没有第三个模块的情况下工作,但在包含第三个模块时抛出以下错误:Error in $: object of type 'closure' is not subsettable
。下面是最小的示例代码。非常感谢您的帮助!
first_module.R
#Define ui
first_module_ui <- function(id) {
ns <- NS(id)
tagList(numericInput(
inputId = ns("first_input"),
label = "First input:",
value = 1
))
}
#Define server logic
first_module_server <- function(input, output, session) {
return(input)
}
second_module.R
#Define ui
second_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("second_input")))
}
#Define server logic
second_module_server <- function(input, output, session, first_module_res) {
ns <- session$ns
observe({
second_input <- first_module_res$first_input + 1
output$second_input <- renderUI({
disabled(textInput(
inputId = ns("second_input"),
label = "Second input:",
value = second_input
))
})
})
return(reactive({second_input}))
}
third_module.R
#Define ui
third_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("third_input")))
}
#Define server logic
third_module_server <- function(input, output, session, second_module_res) {
ns <- session$ns
observe({
third_input <- second_module_res$second_input + 1
output$third_input <- renderUI({
disabled(textInput(
inputId = ns("third_input"),
label = "Third input:",
value = third_input
))
})
})
}
app.R
library(shiny)
library(shinyjs)
# Define UI
ui <- fluidPage(
useShinyjs(),
# Application title
titlePanel("Demo"),
# Sidebar
sidebarLayout(
sidebarPanel(
first_module_ui("first")
),
mainPanel(
second_module_ui("second"),
third_module_ui("third")
)
)
)
# Define server logic
server <- function(input, output, session) {
callModule(first_module_server, "first")
first_module_res <- callModule(first_module_server, "first")
callModule(second_module_server, "second", first_module_res)
second_module_res <- callModule(second_module_server, "second", first_module_res)
callModule(third_module_server, "third", second_module_res)
}
# Run the application
shinyApp(ui = ui, server = server)
您的代码有一些问题:
- 您不需要
observe
,您可以使用reactive
,因为您感兴趣的是 return 值(参见 here) - 您应该将计算值设为反应式
- 你不需要调用一个模块两次
您的代码无法正常工作,因为您 return 来自模块服务器函数的值。从第一个模块,你 return 完整的 input
这允许你在第二个模块中访问第一个模块的 input
中的值,就像你在没有任何模块的情况下访问它一样server
来自主应用程序的功能。这意味着您不需要括号来评估反应式,您可以像使用 input$first_input
.
first_module_res$first_input
但是,第二个模块不是 return input
,而是您创建的反应式(通过 return 值中的 reactive({})
)。这现在成为输入到第三个模块的值,需要用括号计算:second_module_res()
。另请注意,您直接评估反应式,因为它是唯一的 returned 值(而不是第二个模块的完整 input
)。
library(shiny)
library(shinyjs)
#Define ui
first_module_ui <- function(id) {
ns <- NS(id)
tagList(numericInput(
inputId = ns("first_input"),
label = "First input:",
value = 1
))
}
#Define server logic
first_module_server <- function(input, output, session) {
return(input)
}
#Define ui
second_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("second_input")))
}
#Define server logic
second_module_server <- function(input, output, session, first_module_res) {
ns <- session$ns
second_input <- reactive({
first_module_res$first_input + 1
})
output$second_input <- renderUI({
disabled(textInput(
inputId = ns("second_input"),
label = "Second input:",
value = second_input()
))
})
return(reactive({second_input()}))
}
#Define ui
third_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("third_input")))
}
#Define server logic
third_module_server <- function(input, output, session, second_module_res) {
ns <- session$ns
third_input <- reactive({
second_module_res() + 1
})
output$third_input <- renderUI({
disabled(textInput(
inputId = ns("third_input"),
label = "Third input:",
value = third_input()
))
})
}
# Define UI
ui <- fluidPage(
useShinyjs(),
# Application title
titlePanel("Demo"),
# Sidebar
sidebarLayout(
sidebarPanel(
first_module_ui("first")
),
mainPanel(
second_module_ui("second"),
third_module_ui("third")
)
)
)
# Define server logic
server <- function(input, output, session) {
first_module_res <- callModule(first_module_server, "first")
second_module_res <- callModule(second_module_server, "second", first_module_res)
callModule(third_module_server, "third", second_module_res)
}
# Run the application
shinyApp(ui = ui, server = server)
编辑
您可以 return 来自具有多个反应的模块的列表:
library(shiny)
library(shinyjs)
#Define ui
first_module_ui <- function(id) {
ns <- NS(id)
tagList(numericInput(
inputId = ns("first_input"),
label = "First input:",
value = 1
))
}
#Define server logic
first_module_server <- function(input, output, session) {
return(input)
}
#Define ui
second_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("second_input")),
numericInput(
inputId = ns("additional_input"),
label = "Additional input",
value = 5
))
}
#Define server logic
second_module_server <- function(input, output, session, first_module_res) {
ns <- session$ns
second_input <- reactive({
first_module_res$first_input + 1
})
output$second_input <- renderUI({
disabled(textInput(
inputId = ns("second_input"),
label = "Second input:",
value = second_input()
))
})
return(list(
second_input = reactive({second_input()}),
additional_input = reactive({input$additional_input})
))
}
#Define ui
third_module_ui <- function(id) {
ns <- NS(id)
tagList(uiOutput(outputId = ns("third_input")),
verbatimTextOutput(outputId = ns("fourth_output")))
}
#Define server logic
third_module_server <- function(input, output, session, second_module_res) {
ns <- session$ns
third_input <- reactive({
second_module_res$second_input() + 1
})
output$third_input <- renderUI({
disabled(textInput(
inputId = ns("third_input"),
label = "Third input:",
value = third_input()
))
})
output$fourth_output <- renderPrint({
second_module_res$additional_input()
})
}
# Define UI
ui <- fluidPage(
useShinyjs(),
# Application title
titlePanel("Demo"),
# Sidebar
sidebarLayout(
sidebarPanel(
first_module_ui("first")
),
mainPanel(
second_module_ui("second"),
third_module_ui("third")
)
)
)
# Define server logic
server <- function(input, output, session) {
first_module_res <- callModule(first_module_server, "first")
second_module_res <- callModule(second_module_server, "second", first_module_res)
callModule(third_module_server, "third", second_module_res)
}
# Run the application
shinyApp(ui = ui, server = server)