【问题标题】:How to return input values from callModule function in shiny如何从闪亮的callModule函数返回输入值
【发布时间】:2017-04-13 09:41:58
【问题描述】:

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

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

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    您的代码非常接近正确。

    您唯一需要意识到的是,您从模块返回的是一个列表,而不是一个反应值。因此,您不能像响应值一样访问它。但是您可以访问其各个元素,例如反应值。

    因此,虽然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})))
    

    然后app代码就变成了

    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)
    

    【讨论】:

    • 感谢您的回答,这确实解决了问题...我非常专注于闪亮,以至于我显然忘记了有关访问列表中元素的基础知识 ;-) 我明天将奖励赏金,显然仅在 18 小时后才允许。
    • 从一个模块返回多个响应式值确实有点令人困惑和不直观,我第一次也遇到了困难:)
    猜你喜欢
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 2020-06-03
    • 2019-03-07
    • 1970-01-01
    相关资源
    最近更新 更多