闪亮模块之间的通信
Communication between Shiny Modules
我在 shiny 中创建了一个应用程序(用于说明的浓缩示例),其中包含一个无法正常通信的模块。
ui 应通过单击 "Load" 按钮创建一些数据 (DataPack
)(到目前为止有两个元素的 list
)。然后应通过模块绘制数据,而每个模块绘图的 x 轴范围应由 ui.
的 sliderInput
控制
即使创建的数据绘制正确(仅在第一个 运行 上),但我面临的特殊问题是:
- 我假设
restarting interrupted promise evaluation
警告是在 DataPack
尚未创建或传递给模块时创建的。因此,我理解 Datapack
尚未创建时的警告,但在第一次单击 "Load" 按钮后不会。有没有办法避免这种情况?这种行为从何而来?
- 通过单击 "Load" 按钮创建了一些数据 (
DataPack
) 后,滑块会正确更新,反映出所创建数据 (n
) 的(通用)长度。但是,初始值集 (value = c(0, 150)
) 被传递到模块的绘图,而更新值(或之后的任何其他滑块位置)通过在单击 [=36= 之后创建数据(即实际长度)来传递]-按钮不是。为什么?
- 应用程序在第一次 运行 后停止,无法再点击 "Load" 按钮。为什么?
谢谢你!
library(shiny)
library(TTR)
# module interface
Module_ui <- function(id) {
ns <- NS(id)
plotOutput(ns("Plot"))
}
# module server
Module_Server <- function(input, output, session,
DataPack, DataSetName, xlim) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack[[DataSetName]],
xlim = c(xlim[1], xlim[2])) })
}
# app ui
ui <- fluidPage(
fluidRow(
column(
6, fluidRow(h4("Data Generation")),
fluidRow(actionButton("InputButton_GetData", "Load", width = "100%"))),
column(
6, fluidRow(h4("Update Plot")),
sliderInput(
"SliderInput_xAxis",
label = NULL,
min = 0,
max = 150,
value = c(0, 150),
animate = TRUE))),
Module_ui("Plot_1"),
Module_ui("Plot_2")
)
# app server
server <- function(input, output, session) {
DataPack <- eventReactive(
input$InputButton_GetData, {
message("Creating DataPack")
n <- round(runif(1, min = 100, max = 500))
message(n)
DataPack <- NULL
DataPack$one <- rnorm(n)
DataPack$two <- rnorm(n)^2
updateSliderInput(
session = session,
inputId = "SliderInput_xAxis",
value = c(1, n),
min = 1,
max = n)
return(DataPack)
})
callModule(Module_Server, "Plot_1",
DataPack = DataPack(),
DataSetName = "one",
xlim = input$SliderInput_xAxis)
callModule(Module_Server, "Plot_2",
DataPack = DataPack(),
DataSetName = "two",
xlim = input$SliderInput_xAxis)
}
shinyApp(ui, server)
更喜欢将反应直接传递给模块函数。
注意在 callModule(DataPack = DataPack, ....)
中删除了括号和包裹在反应式中的输入,因此在模块函数体中 DataPack()
而不是 DataPack
。
library(shiny)
library(TTR)
# module interface
Module_ui <- function(id) {
ns <- NS(id)
plotOutput(ns("Plot"))
}
# module server
Module_Server <- function(input, output, session,
DataPack, DataSetName, xlim) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack()[[DataSetName]],
xlim = c(xlim()[1], xlim()[2])) })
}
# app ui
ui <- fluidPage(
fluidRow(
column(
6, fluidRow(h4("Data Generation")),
fluidRow(actionButton("InputButton_GetData", "Load", width = "100%"))),
column(
6, fluidRow(h4("Update Plot")),
sliderInput(
"SliderInput_xAxis",
label = NULL,
min = 0,
max = 150,
value = c(0, 150),
animate = TRUE))),
Module_ui("Plot_1"),
Module_ui("Plot_2")
)
# app server
server <- function(input, output, session) {
DataPack <- eventReactive(
input$InputButton_GetData, {
message("Creating DataPack")
n <- round(runif(1, min = 100, max = 500))
message(n)
DataPack <- NULL
DataPack$one <- rnorm(n)
DataPack$two <- rnorm(n)^2
updateSliderInput(
session = session,
inputId = "SliderInput_xAxis",
value = c(1, n),
min = 1,
max = n)
return(DataPack)
})
SliderInput_xAxis_rx <- reactive(input$SliderInput_xAxis)
callModule(Module_Server, "Plot_1",
DataPack = DataPack,
DataSetName = "one",
xlim = SliderInput_xAxis_rx)
callModule(Module_Server, "Plot_2",
DataPack = DataPack,
DataSetName = "two",
xlim = SliderInput_xAxis_rx)
}
shinyApp(ui, server)
编辑:为 Shiny > 1.5 版本推荐的语法更新
Module_Server <- function(id,
DataPack, DataSetName, xlim) {
moduleServer(id,
function(input, output, session) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack()[[DataSetName]],
xlim = c(xlim()[1], xlim()[2])) })
}
)
}
server <- function(input, output, session) {
DataPack <- eventReactive(input$InputButton_GetData, {
message("Creating DataPack")
n <- round(runif(1, min = 100, max = 500))
message(n)
DataPack <- NULL
DataPack$one <- rnorm(n)
DataPack$two <- rnorm(n)^2
updateSliderInput(session = session,
inputId = "SliderInput_xAxis",
value = c(1, n), min = 1, max = n)
return(DataPack)
})
SliderInput_xAxis_rx <- reactive(input$SliderInput_xAxis)
Module_Server("Plot_1",
DataPack = DataPack,
DataSetName = "one",
xlim = SliderInput_xAxis_rx)
Module_Server("Plot_2",
DataPack = DataPack,
DataSetName = "two",
xlim = SliderInput_xAxis_rx)
}
我不确定该应用程序应该做什么,但我认为您必须将电抗导体 DataPack
传递给模块服务器,而不是它的值 returns:
Module_Server <- function(input, output, session,
DataPack, DataSetName, xlim) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack()[[DataSetName]], # note the parentheses
xlim = c(xlim[1], xlim[2])) })
}
callModule(Module_Server, "Plot_1",
DataPack = DataPack, # no parentheses
DataSetName = "one",
xlim = input$SliderInput_xAxis)
callModule(Module_Server, "Plot_2",
DataPack = DataPack, # no parentheses
DataSetName = "two",
xlim = input$SliderInput_xAxis)
我在 shiny 中创建了一个应用程序(用于说明的浓缩示例),其中包含一个无法正常通信的模块。
ui 应通过单击 "Load" 按钮创建一些数据 (DataPack
)(到目前为止有两个元素的 list
)。然后应通过模块绘制数据,而每个模块绘图的 x 轴范围应由 ui.
sliderInput
控制
即使创建的数据绘制正确(仅在第一个 运行 上),但我面临的特殊问题是:
- 我假设
restarting interrupted promise evaluation
警告是在DataPack
尚未创建或传递给模块时创建的。因此,我理解Datapack
尚未创建时的警告,但在第一次单击 "Load" 按钮后不会。有没有办法避免这种情况?这种行为从何而来? - 通过单击 "Load" 按钮创建了一些数据 (
DataPack
) 后,滑块会正确更新,反映出所创建数据 (n
) 的(通用)长度。但是,初始值集 (value = c(0, 150)
) 被传递到模块的绘图,而更新值(或之后的任何其他滑块位置)通过在单击 [=36= 之后创建数据(即实际长度)来传递]-按钮不是。为什么? - 应用程序在第一次 运行 后停止,无法再点击 "Load" 按钮。为什么?
谢谢你!
library(shiny)
library(TTR)
# module interface
Module_ui <- function(id) {
ns <- NS(id)
plotOutput(ns("Plot"))
}
# module server
Module_Server <- function(input, output, session,
DataPack, DataSetName, xlim) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack[[DataSetName]],
xlim = c(xlim[1], xlim[2])) })
}
# app ui
ui <- fluidPage(
fluidRow(
column(
6, fluidRow(h4("Data Generation")),
fluidRow(actionButton("InputButton_GetData", "Load", width = "100%"))),
column(
6, fluidRow(h4("Update Plot")),
sliderInput(
"SliderInput_xAxis",
label = NULL,
min = 0,
max = 150,
value = c(0, 150),
animate = TRUE))),
Module_ui("Plot_1"),
Module_ui("Plot_2")
)
# app server
server <- function(input, output, session) {
DataPack <- eventReactive(
input$InputButton_GetData, {
message("Creating DataPack")
n <- round(runif(1, min = 100, max = 500))
message(n)
DataPack <- NULL
DataPack$one <- rnorm(n)
DataPack$two <- rnorm(n)^2
updateSliderInput(
session = session,
inputId = "SliderInput_xAxis",
value = c(1, n),
min = 1,
max = n)
return(DataPack)
})
callModule(Module_Server, "Plot_1",
DataPack = DataPack(),
DataSetName = "one",
xlim = input$SliderInput_xAxis)
callModule(Module_Server, "Plot_2",
DataPack = DataPack(),
DataSetName = "two",
xlim = input$SliderInput_xAxis)
}
shinyApp(ui, server)
更喜欢将反应直接传递给模块函数。
注意在 callModule(DataPack = DataPack, ....)
中删除了括号和包裹在反应式中的输入,因此在模块函数体中 DataPack()
而不是 DataPack
。
library(shiny)
library(TTR)
# module interface
Module_ui <- function(id) {
ns <- NS(id)
plotOutput(ns("Plot"))
}
# module server
Module_Server <- function(input, output, session,
DataPack, DataSetName, xlim) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack()[[DataSetName]],
xlim = c(xlim()[1], xlim()[2])) })
}
# app ui
ui <- fluidPage(
fluidRow(
column(
6, fluidRow(h4("Data Generation")),
fluidRow(actionButton("InputButton_GetData", "Load", width = "100%"))),
column(
6, fluidRow(h4("Update Plot")),
sliderInput(
"SliderInput_xAxis",
label = NULL,
min = 0,
max = 150,
value = c(0, 150),
animate = TRUE))),
Module_ui("Plot_1"),
Module_ui("Plot_2")
)
# app server
server <- function(input, output, session) {
DataPack <- eventReactive(
input$InputButton_GetData, {
message("Creating DataPack")
n <- round(runif(1, min = 100, max = 500))
message(n)
DataPack <- NULL
DataPack$one <- rnorm(n)
DataPack$two <- rnorm(n)^2
updateSliderInput(
session = session,
inputId = "SliderInput_xAxis",
value = c(1, n),
min = 1,
max = n)
return(DataPack)
})
SliderInput_xAxis_rx <- reactive(input$SliderInput_xAxis)
callModule(Module_Server, "Plot_1",
DataPack = DataPack,
DataSetName = "one",
xlim = SliderInput_xAxis_rx)
callModule(Module_Server, "Plot_2",
DataPack = DataPack,
DataSetName = "two",
xlim = SliderInput_xAxis_rx)
}
shinyApp(ui, server)
编辑:为 Shiny > 1.5 版本推荐的语法更新
Module_Server <- function(id,
DataPack, DataSetName, xlim) {
moduleServer(id,
function(input, output, session) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack()[[DataSetName]],
xlim = c(xlim()[1], xlim()[2])) })
}
)
}
server <- function(input, output, session) {
DataPack <- eventReactive(input$InputButton_GetData, {
message("Creating DataPack")
n <- round(runif(1, min = 100, max = 500))
message(n)
DataPack <- NULL
DataPack$one <- rnorm(n)
DataPack$two <- rnorm(n)^2
updateSliderInput(session = session,
inputId = "SliderInput_xAxis",
value = c(1, n), min = 1, max = n)
return(DataPack)
})
SliderInput_xAxis_rx <- reactive(input$SliderInput_xAxis)
Module_Server("Plot_1",
DataPack = DataPack,
DataSetName = "one",
xlim = SliderInput_xAxis_rx)
Module_Server("Plot_2",
DataPack = DataPack,
DataSetName = "two",
xlim = SliderInput_xAxis_rx)
}
我不确定该应用程序应该做什么,但我认为您必须将电抗导体 DataPack
传递给模块服务器,而不是它的值 returns:
Module_Server <- function(input, output, session,
DataPack, DataSetName, xlim) {
output$Plot <- renderPlot({
message(paste("Plot", DataSetName))
plot(DataPack()[[DataSetName]], # note the parentheses
xlim = c(xlim[1], xlim[2])) })
}
callModule(Module_Server, "Plot_1",
DataPack = DataPack, # no parentheses
DataSetName = "one",
xlim = input$SliderInput_xAxis)
callModule(Module_Server, "Plot_2",
DataPack = DataPack, # no parentheses
DataSetName = "two",
xlim = input$SliderInput_xAxis)