如何从callModule函数返回闪亮的输入值

时间:2017-04-13 09:41:59

标签: r shiny

我目前正在尝试根据this tutorial对我闪亮的应用进行模块化。在我的实际应用中,我有两个selectInput,允许用户选择第一个和最后一个季度结束日期,根据该日期计算某些数据集的某些统计信息。由于可用的季度结束日期取决于实际数据集,并且正在使用不同的数据集,因此我在服务器功能中动态提供choices selectInput参数。过程如下:

  1. 根据数据集的可用季度结束日期动态创建selectInput个对象。
  2. 使用选定的季度结束日期来相应地限制特定数据集。
  3. 我在我的应用程序中一遍又一遍地执行此操作以获取不同的数据集,这就是我现在想要创建模块的原因。但是,我很难获得所选的季度结束日期,然后我可以使用它来限制我的数据集。

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

    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中返回选定的季度结束日期,但我很难理解原因。

1 个答案:

答案 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)