2

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!

Florian
  • 24,425
  • 4
  • 49
  • 80
Rohit Saluja
  • 1,517
  • 2
  • 17
  • 25

1 Answers1

3

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))    
}
Florian
  • 24,425
  • 4
  • 49
  • 80
  • thanks for the prompt response, I have a few question 1) How and why does this works? 2) Since I have not written this piece of code in server.R but in a seperate R file, how can I return a value from this piece of code and use it in showmodal in my server.R code? – Rohit Saluja Jan 19 '18 at 11:19
  • I found my other post, see [here](https://stackoverflow.com/questions/48135448/in-delayed-expression-evaluation-r-shiny-uses-changed-values-of-variables/48135541#48135541). I hope that can help you, there are also links in the comments to further explain the cause! – Florian Jan 19 '18 at 12:38
  • Thanks a lot :) , I am at work currently will surely go through it and might bug you again :p – Rohit Saluja Jan 19 '18 at 12:47
  • Hi Rohit, if you do please check the guidelines [here](https://stackoverflow.com/questions/48343080/how-to-create-a-great-shiny-reproducible-example/). I think that would make it a lot easier to help you. – Florian Jan 19 '18 at 14:23