function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
AniqaaaAniqaaa 

Multiple Pagination

Does the code need to be put in a Controller class?
It doesnt seem to work could someone please help?



String qry = 'select Id,Name from Account where ....';
ApexPages.StandardSetController  acct = new ApexPages.StandardSetController(Database.getQueryLocator(qry));

Here is some example code


public class EnumeratedValues {

public enum OpportunityEnum {Object1, Object2}
}

public with sharing class OppReporting {

      //iterators
      public ApexPages.StandardSetController object1{get; set;}
      public ApexPages.StandardSetController object2{get; set;}
    
      //the current page number for each object
      public integer object1Pg{get; set;}
      public integer object2Pg{get; set;}
    
      //display results
      public List<Opportunity> object1Return {get;set;}
      public List<Opportunity> object2Return {get;set;}

      //number of records to display comes from a custom setting
      public integer numberRecordsToDisplay{get;set;}
      public string setRecordsToDisplay{get;set;}
    
      //pages to display for Task
      public list<integer> object1StatusPagesToDisplay{get;set;}
      public integer selectedPageObject1{get;set;}
    
      //pages to display for object2 summary
      public list<integer> object2PagesToDisplay{get;set;}
      public integer selectedPageObject2{get;set;}

      private Set<Id> newIDsSet;
      public Map<ID,ID> object1IdToTaskID{get; set;}
      public ID selectedObject1{get; set;}
    
      //public Set<String> subjects;
      public list<Opportunity> opps{get; set;}
    
      //max pages to dislay
      public long numberOfPagesToDisplayObject1{get; set;}
      public long numberOfPagesToDisplayObject2{get; set;}
                
      public list<object1List> allObject1List{get;set;}{allObject1List = new list<object1List>();}
      public list<object2List> allObject2List{get;set;}{allObject2List = new list<object2List>();}
               
      public OppReporting(){    
            //get the number of records to display on each page
                  numberRecordsToDisplay = 10;          
      }

      //Task Navig
      public void moveToPageObject1() {
            object1.setPageNumber(selectedPageObject1);
            object1Pg = object1.getPageNumber();
            refreshOutput(EnumeratedValues.OpportunityEnum.Object1,object1);
      }

      //Object2 Summary Navig
      public void moveToPageObject2() {
            object2.setPageNumber(selectedPageObject2);
            object2Pg = object2.getPageNumber();
            refreshOutput(EnumeratedValues.OpportunityEnum.Object2,object2);
      }
    
      public PageReference doSearch() {
            integer numberRecordsToDisplayTemp;//if this is not used numberRecordsToDisplay gets permanently set so user can only increase records per page not decrease
            if (setRecordsToDisplay != null && setRecordsToDisplay != '')
                  numberRecordsToDisplayTemp = integer.valueof(setRecordsToDisplay);
            else
                  numberRecordsToDisplayTemp = numberRecordsToDisplay;
                      
            //1st object
            String qry;     
            //NOTE - Product2__c will have to change to Product2
            integer rowlimit = limits.getLimitQueryRows();

            qry = 'select Id,Primary_Agency_Buyer__c,Account.Name,Name from Opportunity limit :rowlimit';
          
            //get number of records
            list<Opportunity> object1AllRecords = Database.query(qry);

            //get number of pages to display        
            decimal numberOfPagesToDisplay = decimal.valueof(object1AllRecords.size()) / decimal.valueof(numberRecordsToDisplayTemp);
                      
            //round up
            numberOfPagesToDisplayObject1 = numberOfPagesToDisplay.round(ROUNDMODE);
          
            object1StatusPagesToDisplay = new list<integer>();

            //produce list of pages to display
            for (integer i = 1;i<=numberOfPagesToDisplayObject1;i++){
                  object1StatusPagesToDisplay.add(i);
            }
                      
            //need to get into iterator so Prev and Next buttons work on same data
            object1 = new ApexPages.StandardSetController(Database.getQueryLocator(qry));
            object1.setPageSize(numberRecordsToDisplayTemp);
          
            //query the data to display
            refreshOutput(EnumeratedValues.OpportunityEnum.Object1,object1);
          

            //used to render correct section
            object1Pg=1;
          
            //2nd object
                              qry = 'select Id,Primary_Agency_Buyer__c,Primary_Agency_Buyer__r.Name,Name,Sum_Total_Price_del__c, Third_party_Stats_checked__c from Opportunity limit :rowlimit';
                
            //get number of records
            list<Opportunity> object2AllRecords = Database.query(qry);
          
            //get number of pages to display
            integer object2AllSize = object2AllRecords.size();
            decimal numberOfPagesToDisplay2 = decimal.valueof(object2AllSize) / decimal.valueof(numberRecordsToDisplayTemp);
                      
            //round up
            numberOfPagesToDisplayObject2 = numberOfPagesToDisplay2.round(ROUNDMODE);
            object2PagesToDisplay = new list<integer>();

            //produce list of pages to display
            for (integer i = 1;i<=numberOfPagesToDisplayObject2;i++){
                  object2PagesToDisplay.add(i);
            }
                      
            //need to get into iterator so Prev and Next buttons work on same data
            object2 = new ApexPages.StandardSetController(Database.getQueryLocator(qry));
            object2.setPageSize(numberRecordsToDisplayTemp);
          
            //query the data to display
            refreshOutput(EnumeratedValues.OpportunityEnum.Object2,object2);
          
                
            //used to render correct section
            object2Pg=1;    
                
            return null;
      }

      public void refreshOutput(EnumeratedValues.OpportunityEnum OpportunityEnumType,ApexPages.StandardSetController std){
            newIDsSet = new Set<Id>();
            for (sObject eachRec : (List<sObject>)std.getRecords())
                  newIDsSet.add((ID)eachRec.get('id'));
          
            system.debug('size refreshOutput ' + newIDsSet.size());
            Task[] allTks;
            OpportunityLineItem[] thisopplines;
            if (OpportunityEnumType ==  EnumeratedValues.OpportunityEnum.Object1){
                  object1Return = [select Id,Primary_Agency_Buyer__c,Account.Name,Name from Opportunity where Id In :newIDsSet];

            //Build list of object1List wrappers to easily display on page
            object1List newObject1List;
            allObject1List.clear();
            for (Opportunity eachopp: object1Return){
                  allTks=eachopp.Tasks;
                  thisopplines = eachopp.OpportunityLineItems;
                  for (OpportunityLineItem eachoppline: eachopp.OpportunityLineItems){
                        newObject1List = new object1List(<<Add each value to wrapper class>>);
                        allObject1List.add(newObject1List);
                  }
            }
            }else if (OpportunityEnumType ==  EnumeratedValues.OpportunityEnum.Object2){
                  object2Return = [select Id,Primary_Agency_Buyer__c,Account.Name,Name,Sum_Total_Price_del__c,Campaign_Start_Date__c,Campaign_End_Date__c,Complexity__c,Complexity_explanation__c, Third_party_Stats_checked__c from Opportunity where Id In :newIDsSet];

                                                                            
                        thisopplines = eachopp.OpportunityLineItems;
                        for (OpportunityLineItem eachoppline: eachopp.OpportunityLineItems){

                              newObject2List = new object2List((<<Add each value to wrapper class>>);
                              allObject2List.add(newObject2List);
                        }
                  }
    
            }
      }
    
    

    
      public class object1List{
            public object1List(String addID, …){
                  this.thisID=addID;
                  <<Add more>>
            }
          
            public String thisID{get;set;}
            <<Add more>>
      }
    
      public class object2List{
            public object2List(String addID, … ){
                  this.thisID=addID;
<<Add more>>          
}
          
          
            public String thisID{get;set;}
            <<Add more>>
      }   
}



<apex:page>
         <apex:outputPanel rendered="{!object1StatusDisplay}" >
              <p>&nbsp;</p>
               <apex:outputlabel styleclass="largeTitle">object1 Section</apex:outputlabel>
              <p>&nbsp;</p>
            
              <apex:outputPanel id="currentobject1Page" >
                <apex:outputlabel >Current Page {!object1Pg}</apex:outputlabel>
              </apex:outputPanel>
            
              <apex:pageBlockSection >
                    <apex:pageBlockTable var="object1Rec" value="{!allobject1List}" >
                        <apex:column headerValue="Agency">
                            <apex:commandLink target="_blank" action="/{!object1Rec.thisID}" value="{!object1Rec.thisAgency}"/>
                        </apex:column>
                    </apex:pageBlockTable>
                  
             </apex:pageBlockSection>

                   
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject1}" >First
                        <apex:param name="selectedPageobject1" assignTo="{!selectedPageobject1}" value="1" />
             </apex:commandlink>
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject1}" >Previous
               <apex:param name="selectedPageobject1" assignTo="{!selectedPageobject1}" value="{!selectedPageobject1 - 1}" />
            </apex:commandlink>
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject1}" >Next
               <apex:param name="selectedPageobject1" assignTo="{!selectedPageobject1}" value="{!selectedPageobject1 + 1}" />
            </apex:commandlink>
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject1}" >Last
               <apex:param name="selectedPageobject1" assignTo="{!selectedPageobject1}" value="{!numberOfPagesToDisplayobject1}" />
            </apex:commandlink>
             <br />
             <apex:outputPanel layout="block" styleclass="scrollNavig">
                         <apex:repeat value="{!object1StatusPagesToDisplay}" var="pgs" >
                            <apex:commandLink styleclass="rightspace" id="object1Link" action="{!moveToPageobject1}" >{!pgs}
                                <apex:param name="selectedPageobject1" assignTo="{!selectedPageobject1}" value="{!pgs}" />
                            </apex:commandlink>
                         </apex:repeat>
             </apex:outputPanel>
        </apex:outputPanel>

        <apex:outputPanel rendered="{!object2Display}" >
             <p>&nbsp;</p>
             <apex:outputlabel styleclass="largeTitle">object2  Section</apex:outputlabel>
             <p>&nbsp;</p>
      
              <apex:outputPanel id="currentobject2Page" >
                <apex:outputlabel >Current Page {!object2Pg}</apex:outputlabel>
              </apex:outputPanel>
            
              <apex:pageBlockSection >
                    <apex:pageBlockTable var="object2Rec" value="{!allobject2List}" >
                        <apex:column headerValue="Agency">
                            <apex:commandLink target="_blank" action="/{!object2Rec.thisID}" value="{!object2Rec.thisAgency}"/>
                        </apex:column>
                        <apex:column headerValue="ID">
                            <apex:outputLabel value="{!object2Rec.thisID}"/>
                        </apex:column>
                    </apex:pageBlockTable>
                  
             </apex:pageBlockSection>
                   
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject2}" >First
                        <apex:param name="selectedPageobject2" assignTo="{!selectedPageobject2}" value="1" />
             </apex:commandlink>
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject2}" >Previous
               <apex:param name="selectedPageobject2" assignTo="{!selectedPageobject2}" value="{!selectedPageobject2 - 1}" />
            </apex:commandlink>
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject2}" >Next
               <apex:param name="selectedPageobject2" assignTo="{!selectedPageobject2}" value="{!selectedPageobject2 + 1}" />
             </apex:commandlink>
             <apex:commandLink styleclass="rightspace" action="{!moveToPageobject2}" >Last
               <apex:param name="selectedPageobject2" assignTo="{!selectedPageobject2}" value="{!numberOfPagesToDisplayobject2}" />
             </apex:commandlink>
             <br />
           
             <apex:outputPanel layout="block" styleclass="scrollNavig">
                         <apex:repeat value="{!object2PagesToDisplay}" var="pgs" >
                            <apex:commandLink styleclass="rightspace" action="{!moveToPageobject2}" >{!pgs}
                                <apex:param name="selectedPageobject2" assignTo="{!selectedPageobject2}" value="{!pgs}" />
                            </apex:commandlink>
                         </apex:repeat>
                     </apex:outputPanel>
        </apex:outputPanel>

    </apex:outputPanel>
</apex:form>
</apex:pageBlock>


</apex:page>

Saurabh DhobleSaurabh Dhoble

Your code is way too complex to debug, can you simplify a little bit. I would recommend you go through this post to understand the basics of pagination.

Raj.ax1558Raj.ax1558

This code is very complex. You need use 'OFFSET' in a query. Thats make code easy. 

I give you one example to use this code - 

 

list<contact> con = [SELECT id FROM contact LIMIT 10 OFFSET 0];

 

you will use variable for change limit and offset, that will be dynamically chage. 

 

 

mark this as solution for others to get it easily

 

 

Alex.AcostaAlex.Acosta

Best advice I can give is make a service class that does the logic for you and you only have to setup once. You are currently doubling your code by having 2 methods because you want 2 paginated set of sobjects...

 

Here's an example of what I have done in the past when I needed pagination.

 

/**
 * This is a basic pagination service class for the Task Sobject.
 * Constructor requires 2 input values.
 * @Input String soqlString - Query related to what you want to pull back.
 * @Input Integer pageSize - Number of records to be returned at a time. 
 *
 * @auther Alex Acosta
 **/
public with sharing class TaskSetController {

	private String taskQuery		{ get; set; }
	private Integer recordCount		{ get; set; }
	private Boolean hasNext			{ get; set; }
	private Boolean hasPrevious		{ get; set; }
	private Integer offset			{ get; set; }
	private List<Task> tasks		{ get; set; }
	private Integer pageSize		{ get; set; }
	private Integer pageNumber		{ get; set; }
	
	public TaskSetController(String soqlString, Integer pageSize){
		this.taskQuery = soqlString;
		recordCount = 0;
		if(null == pageSize || 0 == pageSize) 
			pageSize = 5;
		this.pageSize = pageSize;		
		offset = 0;
		pageNumber = 1;
		hasNext = false;
		hasPrevious = false;
		tasks = new List<Task>();
		getRecordCount();
	}
	
	public Integer getRecordCount(){
		String soqlString = 'SELECT count() ' + this.taskQuery.subString(this.taskQuery.ToLowerCase().indexOf('from task'));
		if(soqlString.toLowerCase().contains('order by'))
			soqlString = soqlString.substring(0, soqlString.ToLowerCase().indexOf('order by'));
		recordCount = Database.countQuery(soqlString);
		
		return recordCount;
	}
	
	public String getQueryString(){ return this.taskQuery; }
	
	public Integer getPageSize(){ return this.pageSize; }
	
	public List<Task> getRecords(){
		String soqlString = this.taskQuery + ' LIMIT ' + pageSize;

		if(offset > 0)
			soqlString = soqlString + ' OFFSET ' + offset;
		
		tasks = Database.query(soqlString);
		return tasks;
	}
	
	public Boolean getHasNext(){
		if(offset + tasks.size() >= recordCount)	return false;
		return true;
	}
	
	public Boolean getHasPrevious(){
		if(offset == 0)	return false;
		return true;
	}
	
	public List<Task> getNext(){
		offset = offset + pageSize;
		if(pageNumber < getTotalPages())
			pageNumber++;
		return getRecords();
	}
	
	public List<Task> getPrevious(){
		offset = offset - pageSize;
		if(pageNumber > 1)
			pageNumber--;
		return getRecords();
	}
	
	public Integer getCurrentPage(){
		return pageNumber;	
	}
	
	public Integer getTotalPages(){
		return (math.mod(recordCount, pageSize) > 0) ? Integer.valueOf(Math.floor(recordCount/pageSize)) + 1 : recordCount/pageSize;
	}
	
	public List<Task> getFirstPage(){
		pageNumber = 1;
		offset = 0;
		return getRecords();
	}
	
	public List<Task> getLastPage(){
		offset = (getTotalPages()-1) * pageSize;
		pageNumber = getTotalPages();
		return getRecords();
	}
}

 

To control multiple pagination on a single page you would do something like this in your VF controller... Make a variable for each instance, and their own method. This way if anything ever needs to change from the root code, you only have to change it in one place.

public List<Task> notes  { get; set; }
public TaskSetController theNotesController  { get; set; }
    
    public void resetNoteController(){
        theNotesController = new TaskSetController('SELECT CreatedBy.Name, CreatedDate, Description, Id FROM Task WHERE WhoId = \'' + account.PersonContactId + '\' ORDER BY CreatedDate DESC', 10);
        notes = theNotesController.getRecords();
    }
    
    public void getNextSetOfNotes(){
        if(getNotesHasNext())
            notes = theNotesController.getNext();
    }
    
    public Boolean getNotesHasNext(){
        return theNotesController.getHasNext();
    }
    
    public void getPreviousSetOfNotes(){
        if(getNotesHasPrevious())
            notes = theNotesController.getPrevious();
    }
    
    public Boolean getNotesHasPrevious(){
        return theNotesController.getHasPrevious();
    }
    
    public Integer getTaskRecordCount(){
        return theNotesController.getRecordCount();
    }
    
    public Integer getTaskTotalPages(){
        return 0 == theNotesController.getTotalPages() ? 1 : theNotesController.getTotalPages();
    }
    
    public Integer getTaskCurrentPage(){
        return theNotesController.getCurrentPage();
    }
    
    public void getFirstPageOfNotes(){
        notes = theNotesController.getFirstPage();
    }
    
    public void getLastPageOfNotes(){
        notes = theNotesController.getLastPage();
    }

 

...

 

netspidernetspider

Just so you know I produced the code for the pagination which was before OFFSET  was released but still OFFSET will only work for the first 2000 records

 

So if anyone is interested this wil work with whatever number of records you want to through at it up to 50000 and as many objects to paginate

http://stevefouracre.blogspot.co.uk/2011/08/multiple-object-pajination-on-1-vf-page.html