我目前正在尝试根据this tutorial对我闪亮的应用进行模块化。在我的实际应用中,我有两个selectInput
,允许用户选择第一个和最后一个季度结束日期,根据该日期计算某些数据集的某些统计信息。由于可用的季度结束日期取决于实际数据集,并且正在使用不同的数据集,因此我在服务器功能中动态提供choices
selectInput
参数。过程如下:
selectInput
个对象。我在我的应用程序中一遍又一遍地执行此操作以获取不同的数据集,这就是我现在想要创建模块的原因。但是,我很难获得所选的季度结束日期,然后我可以使用它来限制我的数据集。
下面,请找一个说明我问题的小应用。
app.R部分
source("module.R")
ui <- fixedPage(
selectQuartersUI("test"),
textOutput("summary")
)
server <- function(input, output, session) {
### Here I want to save the selected input
#(Use 1:10 for illustration purposes, this would actually be
#quarter end-dates that are dynamic based on the specific data set)
testValues <- callModule(selectQuarters, "test", 1:10)
### Use the selected input (here to simply output them, in actual app to limit data set)
#Using testValues returns long function call, calling testValues() returns "Error: could not find function "testValues""
output$summary <- renderText({
sprintf(paste0("Start: ", testValues(), collapse = "_"))
})
}
shinyApp(ui, server)
module.R part
selectQuartersUI <- function(id) {
ns <- NS(id)
fluidRow(
column(3, htmlOutput(ns("startQuarter"))),
column(3, htmlOutput(ns("endQuarter")))
)
}
selectQuarters <- function(input, output, session, vec_dates) {
vec_dates <- sort(unique(vec_dates))
output$startQuarter <- renderUI({
ns <- session$ns
selectInput(ns("startQuarter"), "Start:", vec_dates[1:(length(vec_dates)-1)],
multiple = FALSE,
selected = max(vec_dates[1:(length(vec_dates)-1)]))
})
output$endQuarter <- renderUI({
ns <- session$ns #See "Using renderUI within modules" part in tutorial
selectInput(ns("endQuarter"), "End:", vec_dates,
multiple = FALSE,
selected = max(vec_dates)) #3nd latest quarter
})
#See tutorial: "If a module wants to return reactive expressions to the calling app,
# then return a list of reactive expressions from the function
# Using c() instead causes the same issues
return(list(reactive({input$startQuarter}),
reactive({input$endQuarter})))
}
失败的部分是在testValues
中返回选定的季度结束日期,但我很难理解原因。
答案 0 :(得分:7)
您的代码非常接近正确。
您唯一需要意识到的是,您从模块返回的是列表,而不是无效值。因此,您无法像反应值那样访问它。但是你可以访问它的各个元素,比如反应值。
因此,虽然testValues()
会导致错误,但testValues[[1]]()
和testValues[[2]]()
会为您提供所需的两个值。
闪亮的应用代码,表明它真的那么简单:
ui <- fixedPage(
selectQuartersUI("test"),
textOutput("summary")
)
server <- function(input, output, session) {
testValues <- callModule(selectQuarters, "test", 1:10)
output$summary <- renderText({
sprintf(paste0("Start: ", testValues[[1]](), " end: ", testValues[[2]]()))
})
}
shinyApp(ui, server)
尽管如此,您可以返回一个命名列表(并将各个元素作为反应值访问)。在模块内部,将return语句修改为
return(list(start = reactive({input$startQuarter}),
end = reactive({input$endQuarter})))
然后应用代码变为
ui <- fixedPage(
selectQuartersUI("test"),
textOutput("summary")
)
server <- function(input, output, session) {
testValues <- callModule(selectQuarters, "test", 1:10)
output$summary <- renderText({
sprintf(paste0("Start: ", testValues$start(), " end: ", testValues$end()))
})
}
shinyApp(ui, server)