Apr 15, 2011

Pagination in Salesforce

We sometimes need to display many records on UI, so it doesn't look good when you display 10000 records on single page. Pagination is the best option you can opt for.


Now question is how you can apply pagination in salesforce with native salesforce look and feel. So here is the answer of this.


Visualforce Page Code :
<apex:page controller="pagingControllerForUser">
    <apex:form >
        <apex:pageBlock >
            
            <apex:pageMessages id="pgm"/>
            
            <apex:pageBlockButtons >
                <apex:commandButton value="Search" action="{!Search}"/>
            </apex:pageBlockButtons>
            
            <apex:pageBlockSection >
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="User Name"/>
                    <apex:inputText value="{!usr.Name}"/>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>

        </apex:pageBlock>

        <apex:pageBlock rendered="{!IF(AllSearchUsers.size != null && AllSearchUsers.size > 0, true , false)}">
            <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav2">
              Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
                  <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
                  <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
                  <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
                  &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
                  <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
                  <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
                  <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
              </apex:outputPanel>
            
            <apex:pageBlockSection columns="1">
                <apex:pageBlockTable value="{!AllSearchUsers}" var="UR">
                    <apex:column headerValue="Name" value="{!UR.Name}"/>
                    <apex:column headerValue="Email" value="{!UR.Email}"/>
                    <apex:column headerValue="Phone" value="{!UR.Phone}"/>
                    <apex:column headerValue="Department" value="{!UR.Department}"/>
                </apex:pageBlockTable>
            </apex:pageBlockSection>
            
            <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav">
              Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
                  <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
                  <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
                  <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
                  &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
                  <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
                  <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
                  <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
              </apex:outputPanel>

        </apex:pageBlock>

    </apex:form>
</apex:page>


This page will show a input field where you can enter user name to be searched. Now when you click search all user by that name get searched, lets say I search with "Test Test". I have 8 users with that name in my organisation. 5 record will be shown at a time on screen, it will be displayed like this.





When we click "Next Page" next 5 records will be displayed, in this case 3 records. Screen will come up like this.





Apex Code :
public class pagingControllerForUser
{
    public List<User> AllSearchUsers
    {
        get
        {
            if(con != null)
                return (List<User>)con.getRecords();
            else
                return null ;
        }
        set;}
    
    public User usr {get; set;}
    
    //Controller
    public pagingControllerForUser()
    {
        AllSearchUsers = new List<User>() ;
        usr = new User() ;
    }
    
     public PageReference Search()
    {   
        if(usr.Name != null)
        {
            con = new ApexPages.StandardSetController(Database.getQueryLocator([select Id , name , email , phone, Department from User where name = :usr.Name]));
 
            // sets the number of records in each page set
            con.setPageSize(5);
        }
        else
        {
            con = null;
        }
        return null ;
    }
    
    //Instantiate the StandardSetController
    public ApexPages.StandardSetController con{get; set;}
    
    //Boolean to check if there are more records after the present displaying records
    public Boolean hasNext
    {
        get
        {
            return con.getHasNext();
        }
        set;
    }
 
    //Boolean to check if there are more records before the present displaying records
    public Boolean hasPrevious
    {
        get
        {
            return con.getHasPrevious();
        }
        set;
    }
 
    //Page number of the current displaying records
    public Integer pageNumber
    {
        get
        {
            return con.getPageNumber();
        }
        set;
    }

    //Returns the previous page of records
    public void previous()
    {
        con.previous();
    }
 
    //Returns the next page of records
    public void next()
    {
        con.next();
    }
}


Any query about this is welcomed.


Cheers

26 comments:

  1. Hi, Ankit.
    Its really helpful.
    Can you please share more samples.
    Thanks

    ReplyDelete
  2. @Narsimha, please let me know what kind of more samples you want (over which topic). I have posted some of the recipes on salesforce cookbook but they are from my blog itself.

    You can find links to my recipes in right side bar.

    ReplyDelete
  3. Can you post a simple example of pagination with the SF Accounts object?

    ReplyDelete
  4. Hi Ankit,

    Thanks for the post. It is really helpful.
    I am facing an issue. When I click on "next" link, next set of records are coming but my URL parameter is disappearing..... Can you please tell me how we can retain the URL parameters also?

    ReplyDelete
  5. Hi Ankit,

    One issue i found is that when we moved to page#3 or more and click on the "back" button of browser, the system will throw the error "Webpage has expired". Can you tell me why its happening so?

    Thanks
    ashii

    ReplyDelete
  6. hello
    i am facing a problem to write test class of pagination.my test class cover 90% part of controller but it cant cover previous() and next() function.
    how can i cover these function in test class.
    how can test these function using system.assert()

    ReplyDelete
  7. Hi Ankit,

    How can I use this or a similar method when using a SOQL query with apex:datatables?

    Thanks.

    ReplyDelete
  8. What if we need to display about 75000 records?

    ReplyDelete
  9. When ever am trying to save this code in vf page am getting an error like The value 'null' is not valid for operator '>'
    Error is in expression '{!IF((AllSearchUsers.size)>0 ,true,false)}' in component in page pagination
    And Could you please explian how can i overget dis error?

    ReplyDelete
  10. hi tarun i was also getting the same error it was due to AllSearchUsers.size > 0
    as if AllSearchUsers.size is null then it cannot be compared with 0.
    so replace {!IF((AllSearchUsers.size)>0 ,true,false)} with

    ReplyDelete
  11. replace {!IF((AllSearchUsers.size)>0 ,true,false)} with

    ReplyDelete
  12. hi tarun i was also getting the same error it was due to AllSearchUsers.size > 0
    as if AllSearchUsers.size is null then it cannot be compared with 0.
    so replace {!IF((AllSearchUsers.size)>0 ,true,false)} with{!IF(AllSearchUsers.size !=null && AllSearchUsers.size > 0 , true , false)}

    ReplyDelete
  13. Yes, it is working great Thank you; But I want to use paging for multiple datatables on single apex page, please help me in this regards.

    ReplyDelete
  14. Nice solution, it works for simple table. WHat about nested table? Is there any way to set con with nested List?

    ReplyDelete
  15. Can you also show the test class for this code

    ReplyDelete
  16. Thank you so much for sharing this. Great help !!

    ReplyDelete
  17. Hi,
    How to test above class below code not covered

    public List AllSearchUsers
    {
    get
    {
    if(con != null)
    return (List)con.getRecords();
    else
    return null ;
    }
    set;}


    return con.getHasNext();
    return con.getHasPrevioust();
    return con.getpageNumber();

    please help me....

    ReplyDelete
  18. I want to display record in VF page with pagination as " << < 1 2 3 4 5 > >> " <,> for next and previous ,<<,>> for first and last page .Also i need to show an indicator of current page . Please help me out

    ReplyDelete
  19. Hi Ankit,

    How to add checkbox and make it selectable

    ReplyDelete
  20. Anyone notice that with con.getRecords(); you´ll only get the amount of records you set in the page size? I´m having big problems trying to get say 100 records. With a page size of 20 I get 5 pages with 100 records each or 5 pages with 20 records each and the same records for each page.

    ReplyDelete
  21. Anyone notice that with con.getRecords(); you´ll only get the amount of records you set in the page size? I´m having big problems trying to get say 100 records. With a page size of 20 I get 5 pages with 100 records each or 5 pages with 20 records each and the same records for each page.

    ReplyDelete
  22. Bro, I want a to a my page when I am clicking to the mouse it's gives to the ascending order type data's of the column of the table and then I clicking to the doubleclick It's giving descending order of the data's of the column in the table so please help me!!!

    ReplyDelete
  23. Nice blog its very informative and useful blog thanks for sharing.
    Looking for Salesforce Admin & Developer Training
    Salesforce Online Training

    ReplyDelete