[SalesForce] Binding StandardSetController to modified list of record gives error

I am having a pagination through StandardSetController in which I need to be able to select multiple record by check-box(I used wrapper class).

But when I am clicking on Next button which calls the below method I get this error.

"Modified rows exist in the records collection!"

public void pnext(){
if(recList != null){
    tempmapofWRP = new Map<Id,boolean> ();
    List<PO_LineItem__c> tempUpdatePOLINE = new List<PO_LineItem__c>();
    for(wrapperRec wrp: recList){
        wrpMap.put(wrp.record.Id,wrp) ;
        tempmapofWRP.put(wrp.record.Id,wrp.check);
    }
    for(wrapperRec wrp:wrpMap.values()){
        tempUpdatePOLINE.add(wrp.record);
    }
    validationRec();
    //con.save();
    system.debug('***con before null*****'+con);
    system.debug('***con after null*****');
    system.debug('****tempUpdatePOLINE****'+tempUpdatePOLINE);
    con = null;
    con = new ApexPages.StandardSetController(tempUpdatePOLINE);
    con.setPageSize(10);
    system.debug('***con new bind*****'+con);
    system.debug('****before caon next*****');
    con.next();
    system.debug('***Next called ****');
    wrltemplist =  new List<wrapperRec>();
    system.debug('***before getrecordcall *****');
    wrltemplist  = getrecordList();
    for(wrapperRec wrp: wrltemplist ){
        if(wrpMap.containsKey(wrp.record.Id)){
            wrp.check=wrpMap.get(wrp.record.Id).check;
        }
    }
}
else{
    wrltemplist =  new List<wrapperRec>();
    wrltemplist  = getrecordList();
}
}  

what to do in this scenario(I also need to maintain the check-box count in my code so that is why I am using map and again binding the values to displaying list which is "wrltemplist")

EDIT Version with deep clone DIDN'T Worked:

    Public void pnext(){
   con.next();
} 

AND the controller deepclone code is:

Public List<wrapperRec> getrecordList() {
    List<wrapperRec>recListtemp = new List<wrapperRec>();
    recListtemp = recListtoReturn  ;
    recList = new List<wrapperRec>();
    system.debug('****recListtemp *****'+recListtemp );
    system.debug('***inside getrecordList****');
    try{
        if(con.getRecords() != null){
            system.debug('***con not null****');
            for (PO_LineItem__c poLineOb : (List<PO_LineItem__c>)con.getRecords().deepClone(true, true, true)){
                 system.debug('***inside of for loop to getRecords***');
                 wrapperRec rec = new wrapperRec(poLineOb ,false);
                 recList.add(rec);   
            } 
            if(recListtemp != null){
                system.debug('****recListtemp not null*****');
                for(wrapperRec wrp: recListtemp ){
                     wrpMap.put(wrp.record.Id,wrp) ;
                }
                system.debug('****wrpMap*****'+wrpMap.values());
                for(wrapperRec wrp: recList){
                    if(wrpMap.containsKey(wrp.record.Id)){
                        wrp.check=wrpMap.get(wrp.record.Id).check;
                        wrp.record = wrpMap.get(wrp.record.Id).record;
                    }
                }
                system.debug('****after second 2 wrap for loop*****');
             }
        }

        recListtoReturn  = recList ;
        system.debug('****recListtoReturn  *****'+recListtoReturn  );
        return recListtoReturn  ;
    }
    catch(Exception ex){
        ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'No Open OP Line Item Record for this Supplier'));
        return null;
    }
}

But this dont works. If i edit values on any page it run into above mentioned error .. What I am doing wrong!!

Best Answer

This is a "safety" feature, in that it prevents you from accidentally losing changes to records in the standard set controller.

You can prevent these values from changing by avoiding making any updates to records retrieved from controller.getRecords() in apex and only using apex:outputfield in the visualforce page.

If the values need to change and you need to handle that you can avoid the safety feature by deep cloning the list so that the records you're working with and modifying those instead.

List<sObject> modifiable = controller.getRecords().deepClone(true, true, true);
Related Topic