Reputation: 1517
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
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