Rohit Saluja
Rohit Saluja

Reputation: 1517

Create UI dynamically

Background:

I have fileInput named btnUploadMonthlyfile using which user will upload the data file. The uploaded data file contains a field named 'Products'. On click of btnUploadMonthlyfile I want to show a pop-up which should contain a box for each of the distinct Product present in uploaded file and inside the box of each Product, I want to show some summary/metrics related to that Product

I have written below piece of code to achieve the same

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 written in R script which is sourced in 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))    
}

Note:- fcnDoSomeProcessingOnDates(dtToProcess) is some function which does processing and returns a table based on Product value present in dtToProcess, So for every product the function will return a table with distinct values

Problem: The above code create dynamic boxes based on number of Products present in the uploaded file but the datatable which is displayed under box for each product box is always the last one i.e. the value of lDateInformationTable contains the box with the data table processed in last iteration of the loop.

I have debugged the function fcnDoSomeProcessingOnDates and it always return the correct data table based on product.

To me it seems that may be the value of the lDateInformationTable is acting as by reference due to which it always contains the data table processed in last iteration of the loop.

Any help would be much appreciated!

Upvotes: 2

Views: 103

Answers (1)

Florian
Florian

Reputation: 25385

I have encountered this issue before, and using lapply instead of a for loop solves the issue. This has to do with the fact that the created objects are not evaluated at once, and reference variables in your for-loop that change. So try and replace your for-loop with something like:

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))    
}

Upvotes: 3

Related Questions