[英]Shiny reactivity not working in subModules
因为我的shiny
应用程序已经变得很大,所以我最近将一些代码放入模块中(也可以在不同的地方多次重用代码)。 不知何故,部分代码无法按预期工作。
在此示例中,我有一个模块,该模块根据输入元素过滤数据并返回反应性data.frame
。 在mainPanel中,我有一个模块,该模块根据过滤后的数据创建一个dataTable
。 但是反应性不起作用,当我更改selectInput
, dataTable
不会更新。
library(shiny)
library(DT)
filtersUI <- function(id) {
ns <- NS(id)
selectizeInput(
ns("Species"), label = "Species",
choices = levels(iris$Species),
selected = "virginica"
)
}
filters <- function(input, output, session, .data) {
inputs <- reactive({
list("Species" = input[["Species"]])
})
reactive({
.data[.data$Species %in% inputs()[["Species"]], ]
})
}
dataTableUI <- function(id) {
ns <- NS(id)
DT::dataTableOutput(ns("data.table"))
}
dataTable <- function(input, output, session, .data) {
output$data.table <- DT::renderDataTable({
DT::datatable(.data)
})
}
appUI <- function(id) {
ns <- NS(id)
sidebarLayout(
sidebarPanel(
filtersUI(ns("filter"))
),
mainPanel(
dataTableUI(ns("data.table"))
)
)
}
app <- function(input, output, session, .data) {
data.subset <- callModule(filters, "filter", .data = .data)
callModule(dataTable, "data.table", .data = data.subset())
}
ui <- fluidPage(
appUI("app")
)
server <- function(input, output, session) {
callModule(app, "app", .data = iris)
}
shinyApp(ui, server)
但是,当将代码从subModules复制到app
模块时,代码可以正常工作:
library(shiny)
library(DT)
appUI <- function(id) {
ns <- NS(id)
sidebarLayout(
sidebarPanel(
selectizeInput(
ns("Species"), label = "Species",
choices = levels(iris$Species),
selected = "virginica"
)
),
mainPanel(
DT::dataTableOutput(ns("data.table"))
)
)
}
app <- function(input, output, session, .data) {
inputs <- reactive({
list("Species" = input[["Species"]])
})
data.subset <- reactive({
.data[.data$Species %in% inputs()[["Species"]], ]
})
output$data.table <- DT::renderDataTable({
DT::datatable(data.subset())
})
}
ui <- fluidPage(
appUI("app")
)
server <- function(input, output, session) {
callModule(app, "app", .data = iris)
}
shinyApp(ui, server)
我知道在这个简单的示例中,模块化结构看起来有些矫kill过正,但是在我的真实应用中,模块中有很多代码,为了使此示例最小化,我删除了这些代码。 因此,有一个使用与第一个代码段相同的模块化结构的解决方案会很好。 任何想法为什么会失败?
您在创建带有子模块的可复制示例方面做得非常好。 但是,该问题实际上与子模块没有任何关系。 您只需要以不同的方式传递反应对象data.subset
。 代替
callModule(dataTable, "data.table", .data = data.subset())
你应该使用
callModule(dataTable, "data.table", .data = data.subset)
传递电抗本身而不是其当前值。 然后可以像这样在DT::renderDataTable
“解析”该值
output$data.table <- DT::renderDataTable({
DT::datatable({.data()})
})
您进行编码的方式是,“构造时”的数据即未过滤的数据集被发送到模块,并且一路无法观察到。
需要明确的是:注释行( ## remove parantheses here
, ## add parantheses here
)是我从原始代码中唯一更改的行。
library(shiny)
library(DT)
filtersUI <- function(id) {
ns <- NS(id)
selectizeInput(
ns("Species"), label = "Species",
choices = levels(iris$Species),
selected = "virginica"
)
}
filters <- function(input, output, session, .data) {
inputs <- reactive({
list("Species" = input[["Species"]])
})
reactive({
.data[.data$Species %in% inputs()[["Species"]], ]
})
}
dataTableUI <- function(id) {
ns <- NS(id)
DT::dataTableOutput(ns("data.table"))
}
dataTable <- function(input, output, session, .data) {
output$data.table <- DT::renderDataTable({
DT::datatable({.data()}) ## add parantheses here
})
}
appUI <- function(id) {
ns <- NS(id)
sidebarLayout(
sidebarPanel(
filtersUI(ns("filter"))
),
mainPanel(
dataTableUI(ns("data.table"))
)
)
}
app <- function(input, output, session, .data) {
data.subset <- callModule(filters, "filter", .data = .data)
callModule(dataTable, "data.table", .data = data.subset) ## remove parantheses here
}
ui <- fluidPage(
appUI("app")
)
server <- function(input, output, session) {
callModule(app, "app", .data = iris)
}
shinyApp(ui, server)
综上所述,以下是郑承晚对类似问题的引用
嗨,马克,linkedScatter中的代码本身是正确的。 但是,当调用callModule时,您希望通过名称(car_data)传递反应式本身而不读取它(car_data())。
callModule(linkedScatter,“ scatters”,car_data)
这类似于如何通过名称将函数传递给lapply之类的方法:
lapply(字母,toupper)#作品
lapply(字母,toupper())#不起作用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.