2017-04-13 63 views
4

我目前正在尝试基于this tutorial模块化我的闪亮应用程序。在我的实际应用程序中,我有两个允许用户选择第一个和最后一个季度结束日期的selectInput,根据该日期计算某些数据集的一些统计数据。由于可用的四分之一日期取决于实际数据集,并且有不同的数据集在使用,因此我在服务器功能中动态输入choices参数selectInput。过程如下:如何从闪亮的callModule函数返回输入值

  1. 动态创建selectInput对象,条件是数据集的可用季度结束日期。
  2. 使用选定的季度结束日期来相应地限制特定的数据集。

我一遍又一遍地在我的应用程序中为不同的数据集做这个,这就是为什么我现在要创建一个模块。然而,我很努力地将选定的四分之一终止日期返回,然后我可以用它来限制我的数据集。

下面,请找到一个小应用程序,说明我的问题。

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部分

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返回选定季度结束日期的一部分,但我努力想明白为什么。

回答

4

您的代码非常接近正确。

您唯一需要认识到的是,您从模块返回的内容是列表,而不是反应性值。因此,您无法像访问活动值那样访问它。但是你可以访问它的个别元素,比如被动值。

所以虽然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) 
+0

感谢您的回答,这确实解决了问题...我太专注于亮,我明显忘记了关于访问列表中的元素的基础知识;-)明天我会奖赏赏金,显然这只在18小时后才允许。 –

+0

从模块中返回多个反应值确实有点令人困惑和不直观,我也第一次努力:) –