2017-04-13 33 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

從模塊中返回多個反應值確實有點令人困惑和不直觀,我也第一次努力:) –