I am using StandardSetController of the type QueryLocator for my solution. When I try to merge Save and Next together on Next button with Save being on action and next being on oncomplete JavaScript(executed through actionFunction), the button only executes once, the subsequent button press throws this exception on page "Modified rows exist in the records collection!". For Reference - if I keep next separate(no oncomplete script and action doing the next operation) then it works perfectly, but my requirement is merge them together. Here is the code(trimmed to show relevant parts):


   <apex:form id="TheForm">
      <!-- search results table      -->
      <apex:pageBlock id="TablePanel">
         <apex:pageblockButtons >
             <apex:commandButton action="{!save}" value="Save Records" reRender="TablePanel"/>
         <div id="tableButtons">
            <span class="page-buttons" style="float: left; margin-bottom: 5px;"> <apex:commandButton disabled="{!!StdSetControllerDetCen.hasprevious}" value="Previous" action="{!save}" rerender="TablePanel" oncomplete="onCompleteJSFunc2();"/> 

**<apex:commandButton disabled="{!!StdSetControllerDetCen.hasnext}" value="Next"
                  action="{!save}"  oncomplete="onCompleteJSFunc();" rerender="TablePanel"/>**


            <!-- Account table -->
            <apex:facet name="stop">
               <apex:pageBlockTable value="{!DetailCensusList}" var="a">
                  <!-- bunch of columns with inputfields-->

      <apex:actionFunction name="NextPage" action="{!StdSetControllerDetCen.next}" reRender="TablePanel"/>
      <apex:actionFunction name="PreviousPage" action="{!StdSetControllerDetCen.previous}" reRender="TablePanel"/>

   <script type="text/javascript">
       function onCompleteJSFunc(){
       function onCompleteJSFunc2(){        


public with sharing class EmployeeWCPricingController {
    // account and selection set/variables

    public Integer PageNumber;

    public EmployeeWCPricingController(ApexPages.StandardController controller){

        DetCenList = new list<DCWrapperClass>();  
        if(allCensus.size() != 0)
            Totalrecords = allCensus.size();

    * StdSetControllerDetCen - paging through the Account list
    public ApexPages.StandardSetController StdSetControllerDetCen {
        get {
            if(StdSetControllerDetCen == null) {
                StdSetControllerDetCen = new ApexPages.StandardSetController(Database.getQueryLocator(QueryDetailCensus));
                // sets the number of records in each page set
                PageNumber = StdSetControllerDetCen.getPageNumber();
            return StdSetControllerDetCen ;


    * getCurrentDetCenList  - return an list for the table
    public list<DCWrapperClass> getDetailCensusList (){
        DetCenList = new list<DCWrapperClass>();
        for (APTS_LTC_Census__c a : (list<APTS_LTC_Census__c>)StdSetControllerDetCen.getRecords()){
            DetCenList.add(new DCWrapperClass(a, DCSelectedSet.contains(a.Id)));
        return DetCenList ;

    public void save(){


  • The nextFunction and prevFunction in controller are the things I have tried. Those don't work either. Jun 14, 2019 at 18:53

2 Answers 2


To avoid this error, you can write your own methods:

public void goPrev() {
public void goNext() {

Which you'd call appropriately:

<apex:commandButton disabled="{!!StdSetControllerDetCen.hasprevious}" 
   value="Next" action="{!goPrev}" rerender="TablePanel"/>**
<apex:commandButton disabled="{!!StdSetControllerDetCen.hasnext}" 
   value="Next" action="{!goNext}" rerender="TablePanel"/>**

There shouldn't be any need to use the JavaScript functions to separate the two methods.

  • StdSetControllerDetCen.save(); StdSetControllerDetCen.next(); putting them together doesn't work, the page stays at the current page, the list saves in background doesn't reflect on screen. This is the reason I shifted to putting one on onclick JS Jun 18, 2019 at 18:25

I was able to resolve in a dirty way. I was trying to avoid it but this is all I have.

updated get function: public list getDetailCensusList (){ CurrentPageNumber = StdSetControllerDetCen.getPageNumber(); system.debug('//1'+CurrentPageNumber +PageNumber ); System.debug('%%%'+CurrentPageNumber); if(NextPressed != null && NextPressed == true) StdSetControllerDetCen.setpageNumber(PageNumber); else if(PrevPressed != null && PrevPressed == true) StdSetControllerDetCen.setpageNumber(PageNumber1); System.debug('***Getdc2'+StdSetControllerDetCen); DetCenList = new list(); for (APTS_LTC_Census__c a : (list)StdSetControllerDetCen.getRecords()){ DetCenList.add(new DCWrapperClass(a, DCSelectedSet.contains(a.Id))); } System.debug('***Getdc3'+StdSetControllerDetCen); NextPressed = false; PrevPressed = false; return DetCenList ; }

And these are my new save methods(separate for next and prev): public void saveNext(){ PageNumber = StdSetControllerDetCen.getPageNumber(); system.debug('//'+PageNumber ); StdSetControllerDetCen.save(); system.debug('//'+PageNumber ); NextPressed = true;

public void savePrev(){

    PageNumber1 = StdSetControllerDetCen.getPageNumber();
    system.debug('***/*/?'+PageNumber1 );
    PrevPressed = true;
    system.debug('***/*/'+PageNumber1 );


So in short I am manipulating the setPageNumber values to always navigate to right value.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .