Pagination using StandardSetController with wrapper class

Pagination using StandardSetController with wrapper class without losing data during pagination

Click here for Demo – Pagination with wrapper

Very often, we need pagination in our visualforce page, and we use wrapper class to show the records with checkboxes in pageBlockTable. We use the standardSetController for pagination, display checkboxes for each record BUT while paginating, the value of the selected checkboxes are gone, it doesn’t retain during paginating.

This is because the list that we use to display records on page, is getting refreshed everytime, and not retaining the values. So, to hold or retain the values during pagination, we will see how we can use Pagination using StandardSetController with wrapper class without losing data during pagination/ paginating (moving next or previous).


PaginationImage,Pagination using StandardSetController with wrapper class

Contact pagination – Wrapper Class – With checkboxes


So, to overcome this, we will not use the direct list from standardSetController, instead of that we’ll use a map to show the values on page. This map will always contain the correct values of checkboxes (for retaining purpose), we will use map on visualforce page pageBlockTable. Whenever user clicks on next or previous, first or last, we store the copy of records with checkbox value in map, so that even if the wrapper list is refreshed with next set of records, we can store the checkbox values for previous set of records.

Below is the code snippet you can look at, and we have a demo link as well, just to give you an idea how it works.

Visualforce Page Code:

<apex:page controller="contactPaginationController" docType="html-5.0" tabStyle="Contact">
   <apex:sectionHeader title="Contact" subtitle="Contact Pagination" />
    <apex:form id="theForm">
      <apex:pageBlock title="All Contacts" rendered="{!wrapperRecordList.size!=0}" id="pbId" >
        <apex:pageBlockTable value="{!wrapperRecordList}" var="cont">
           <apex:column headerValue="Select">
             <apex:inputCheckbox value="{!cont.isSelected}"/>
           <apex:column headerValue="Name">
             <apex:outputField value="{!}"/>
           <apex:column headerValue="Email">
             <apex:outputField value="{!cont.contactRecord.Email}"/>
           <apex:column headerValue="Phone">
            <apex:outputField value="{!cont.contactRecord.Phone}"/>

 <!-- Action Buttons visible on bottom of page for pagination -->
       <apex:outputPanel style="text-align:center;" layout="block">
          <apex:commandButton value="First" reRender="pbId" action="{!first}" disabled="{!NOT(hasPrevious)}" status="paginationStatus"/>
          <apex:commandButton value="Previous" rerender="pbId" action="{!previous}" disabled="{!NOT(hasPrevious)}" status="paginationStatus"/>&nbsp;Page {!pageNumber} of {!totalPages}&nbsp;
          <apex:commandButton value="Next" rerender="pbId" action="{!next}" disabled="{!NOT(hasNext)}" status="paginationStatus"/>
          <apex:commandButton value="Last" rerender="pbId" action="{!last}" disabled="{!NOT(hasNext)}" status="paginationStatus"/>
          <apex:actionStatus id="paginationStatus">
             <apex:facet name="start">
                 Please wait...<img src="/img/loading32.gif" style="width: 18px;"/>

Apex Controller:

public class contactPaginationController{

 //variable used in page.
 Public Integer size{get;set;}
 Public Integer noOfRecords{get; set;}
 public List<SelectOption> paginationSizeOptions{get;set;}
 public static final Integer QUERY_LIMIT = 10000;
 public static final Integer PAGE_SIZE = 5;

 public List <WrapperClass> wrapperRecordList{get;set;}
 Map<Id, WrapperClass> mapHoldingSelectedRecords{get;set;}

 //constructor calling init method.
 public contactPaginationController(){
   mapHoldingSelectedRecords = new Map<Id, WrapperClass>();


//Init method which queries the records from standard set controller.
 public void init() {
 wrapperRecordList = new List<WrapperClass>();
 for (Contact cont : (List<Contact>)setCon.getRecords()) {
 if(mapHoldingSelectedRecords != null && mapHoldingSelectedRecords.containsKey({

   wrapperRecordList.add(new WrapperClass(cont, false));

 /** Instantiate the StandardSetController from a query locater*/
 public ApexPages.StandardSetController setCon {
 get {
 if(setCon == null) {
   setCon = new ApexPages.StandardSetController(Database.getQueryLocator([SELECT Id,Name, Email, Phone FROM Contact LIMIT : QUERY_LIMIT ]));

   // sets the number of records to show in each page view
   return setCon;

 /** indicates whether there are more records after the current page set.*/
 public Boolean hasNext {
 get {
   return setCon.getHasNext();

 /** indicates whether there are more records before the current page set.*/
 public Boolean hasPrevious {
 get {
   return setCon.getHasPrevious();

 /** returns the page number of the current page set*/
 public Integer pageNumber {
 get {
   return setCon.getPageNumber();

 /** return total number of pages for page set*/
   Public Integer getTotalPages(){
     Decimal totalSize = setCon.getResultSize();
     Decimal pageSize = setCon.getPageSize();
     Decimal pages = totalSize/pageSize;
     return (Integer)pages.round(System.RoundingMode.CEILING);

 /** returns the first page of the page set*/
 public void first() {

 /** returns the last page of the page set*/
 public void last() {

 /** returns the previous page of the page set*/
 public void previous() {

 /** returns the next page of the page set*/
 public void next() {

 //This is the method which manages to remove the deselected records, and keep the records which are selected in map.
 private void updateSearchItemsMap() {
 for(WrapperClass wrp : wrapperRecordList){
     mapHoldingSelectedRecords.put(, wrp);
  if(wrp.isSelected == false && mapHoldingSelectedRecords.containsKey({

 //wrapper class being used for checkbox showing.
 public class WrapperClass {
 public Boolean isSelected {get;set;}
 public Contact contactRecord {get;set;}
 public WrapperClass(Contact contactRecord, Boolean isSelected) {
    this.contactRecord = contactRecord;
    this.isSelected = isSelected;


Click here for Demo – Pagination with wrapper

This is just an example we are taking here (i.e. display contacts with checkboxes), there can be several other scenarios as well, where you might have some inputField in one column of the pageBlockTable, and you need to retain the values of inputfield during pagination.

There also you can use this concept of Pagination using StandardSetController with wrapper class without losing data during pagination.

This is also very important because this kind of scenario is included for sure in Advanced Developer certification exam exercise, where you have to do pagination with either checkboxes or inputField in pageBlockTable.

Hope this post will give you a better idea about pagination and that too with wrapper classes.

Happy coding !! 🙂

Permanent link to this article:


    • Rajesh P on September 13, 2017 at 1:33 pm
    • Reply

    Hi the above example is very helpfull, can you please help me, how can I get selected contact ids to next page to perform certain actions like sending mails etc

    • Amruta on March 1, 2020 at 9:16 pm
    • Reply

    Can i know the test class for above example

  1. Can you explain the key advantages of using a wrapper class in conjunction with StandardSetController for pagination in Salesforce Visualforce pages, and how does it help in retaining data during pagination?

Leave a Reply

Your email address will not be published.