动态创建UI

时间:2018-01-19 07:49:20

标签: r list user-interface shiny

背景:

我有一个名为btnUploadMonthlyfile的fileInput,用户将使用该文件上传数据文件。上传的数据文件包含名为' Products'的字段。点击btnUploadMonthlyfile我想显示一个弹出窗口,其中应包含上传文件中每个不同产品的框以及每个产品的框内,我想显示一些与此相关的摘要/指标产品

我在下面写了一段代码来实现相同的

Server.R

     observeEvent(input$btnMonthlySanityAppend,
                 {
                    sFilePath<-input$btnUploadMonthlyFileForAppend
                    dtUploadedFile<-as.data.table(read_csv(sFilePath$datapath))

                  lReturn <- fcnUploadSanityCheckMonthly(dtUploadedFile)
                        showmodal(modaldialog(
                        title="Summary",
                        lReturn$Display
                        ))    
                 }
     )

fcnUploadSanityCheckMonthly用R脚本编写,源自global.R

fcnUploadSanityCheckMonthly <- function(dtUploadedFile){
    lUniqueProductsITable <- uniqueN(dtUploadedFile,by = c("Product_ID"))
    lUniqueProductName <- unique(dtUploadedFile[,"Product_Name"])
    lBoxList <- vector("list",lUniqueProductsITable)
    dtToProcess <- copy(dtUploadedFile)
    for (i in 1:lUniqueProductsITable){
        tags$br()
        tags$hr()            
        sProduct <- lUniqueProductName[i]
        dtFilteredOnProduct <- dtToProcess[dtToProcess[["Product_Name"]] %in% sProduct ]
        dtDataInfo <- fcnDoSomeProcessingOnDates(dtToProcess)
        lDateInformationTable <- box(title=sTitle  ,width=12,status = "primary",solidHeader = T,collapsible = T,collapsed = T,
       renderDataTable(dtDataInfo ,options=list(scrollX=T))
       )

     lBoxList[[i]] <- box (width = 12,status = "primary",solidHeader = T,collapsible = T,collapsed = T,
     title = lUniqueProductName[i],
     lDateInformationTable
     )
    }
    return(list(Display=lBoxList))    
}

注意: - fcnDoSomeProcessingOnDates(dtToProcess)是一个函数,它根据dtToProcess中的Product值进行处理并返回一个表,因此对于每个产品,该函数将返回一个具有不同值的表

  

问题:   上面的代码根据上传文件中存在的产品数量创建动态框,但每个产品框的框下显示的数据表始终是最后一个,即lDateInformationTable的值包含处理数据表的框在循环的最后一次迭代中。

我调试了函数fcnDoSomeProcessingOnDates,它总是根据产品返回正确的数据表。

对我而言,似乎可能是lDateInformationTable的值正在作为引用,因为它总是包含在循环的最后一次迭代中处理的数据表。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

之前我遇到过这个问题,使用lapply代替for循环解决了这个问题。这与以下事实有关:创建的对象不会立即计算,而for循环中的引用变量也会发生变化。因此,尝试用以下内容替换你的for循环:

fcnUploadSanityCheckMonthly <- function(dtUploadedFile){
    lUniqueProductsITable <- uniqueN(dtUploadedFile,by = c("Product_ID"))
    lUniqueProductName <- unique(dtUploadedFile[,"Product_Name"])
    lBoxList <- vector("list",lUniqueProductsITable)
    dtToProcess <- copy(dtUploadedFile)
    lapply(i in 1:lUniqueProductsITable), function(i)
    {   tags$br()
        tags$hr()            
        sProduct <- lUniqueProductName[i]
        dtFilteredOnProduct <- dtToProcess[dtToProcess[["Product_Name"]] %in% sProduct ]
        dtDataInfo <- fcnDoSomeProcessingOnDates(dtToProcess)
        lDateInformationTable <- box(title=sTitle  ,width=12,status = "primary",solidHeader = T,collapsible = T,collapsed = T,
       renderDataTable(dtDataInfo ,options=list(scrollX=T))
       )
       }

     box(width = 12,status = "primary",solidHeader = T,collapsible = T,collapsed = T,
     title = lUniqueProductName[i],
     lDateInformationTable
     )
    }
    )
    return(list(Display=lBoxList))    
}