Visualforce Pagination with Dynamic Search

This post has a working example of dynamic search in a Visualforce page and the results shown with pagination.

There are 4 field search criteria including date fields too which makes it more interesting.  The results upon clicking Search will display below the Search section with 4 buttons to paginate.  The Next/Last Page buttons grey out when there are no further records in the results.

APB

Apex Controller


public with sharing class AccountMultipleSearchWithPagenationCLS {
public Account acc{get;set;}
public List<Account> accountList {get;set;}
// create a list of strings to hold the conditions
List<string> conditions = new List<string>();
private integer totalRecs = 0;
private integer OffsetSize = 0;
private integer LimitSize= 10;
public AccountMultipleSearchWithPagenationCLS(){
system.debug('==>AccountMultipleSearchWithPagenationCLS is calling==>');
acc = new Account();
//accountList = new List<Account>();
}
public void searchAcc(){
totalRecs = 0;
OffsetSize = 0;
if(accountList !=null && accountList.size()>0){
accountList=null;
}
searchAccounts ();
conditions.clear();
}
public Void searchAccounts(){
System.debug('Total Records is ==>'+totalRecs);
System.debug('OffsetSize is ==>'+OffsetSize);
if(accountList != null && !accountList.isEmpty()){
accountList.clear();
}
String strQuery ='SELECT Id,Name,AccountNumber,CreatedDate,Phone,Website,Industry,AnnualRevenue From Account';
if(acc.Created_From_Date__c !=null){
String fromDate = acc.Created_From_Date__c+'';
fromDate = fromDate.split(' ',0)[0]+'T00:00:00.000Z';
conditions.add('CreatedDate >='+fromDate);
}
if(acc.Created_To_Date__c !=null){
String toDate = acc.Created_To_Date__c+'';
toDate = toDate.split(' ',0)[0]+'T23:59:59.000Z';
conditions.add('createdDate <='+toDate);
}
if(acc.Name !=null && acc.Name !=''){
conditions.add('Name Like \'%' +acc.Name +'%\' ');
}
if(acc.AccountNumber !=null && acc.AccountNumber !=''){
conditions.add('AccountNumber Like\'%' +acc.AccountNumber +'%\' ');
}
if (conditions.size() > 0) {
strQuery += ' WHERE ' + conditions[0];
for (Integer i = 1; i < conditions.size(); i++)
strQuery += ' AND ' + conditions[i];
}
if(totalRecs !=null && totalRecs ==0){
List<Account> accTemp = Database.query(strQuery);
totalRecs = (accTemp !=null &&accTemp.size()>0)?accTemp.size():0;
}
system.debug('strQuery ==>'+strQuery );
// add sort and limits at the end
strQuery += ' ORDER BY Name ASC, CreatedDate DESC LIMIT :LimitSize OFFSET :OffsetSize';
accountList =Database.query(strQuery);
//conditions.clear();
//return accountList.size();
}
public void FirstPage()
{
OffsetSize = 0;
searchAccounts();
}
public void previous()
{
OffsetSize = (OffsetSize-LimitSize);
searchAccounts();
}
public void next()
{
OffsetSize = OffsetSize + LimitSize;
searchAccounts();
}
public void LastPage()
{
OffsetSize = totalrecs – math.mod(totalRecs,LimitSize);
searchAccounts();
}
public boolean getprev()
{
if(OffsetSize == 0){
return true;
}
else {
return false;
}
}
public boolean getnxt()
{
if((OffsetSize + LimitSize) > totalRecs){
return true;
}
else {
return false;
}
}
}

Visualforce Page


<apex:page controller="AccountMultipleSearchWithPagenationCLS" action="{!searchAcc}" >
<script type="text/javascript">
window.onload=function() {
// document.getElementById("{!$Component.thePb.thepbs.accName}").focus();
}
</script>
<apex:form >
<apex:pageBlock id="thePb" title="Account Details To Search">
<apex:pageblockSection id="thepbs">
<apex:inputField value="{!acc.Created_From_Date__c}" />
<apex:inputField value="{!acc.Created_To_Date__c}"/>
<apex:inputField value="{!acc.Name}" required="false" id="accName"/>
<apex:inputfield value="{!acc.accountNumber}"/>
</apex:pageblockSection>
<apex:pageblockButtons location="bottom">
<apex:commandButton value="Search" action="{!searchAcc}" />
</apex:pageblockButtons>
</apex:pageBlock>
<apex:pageBlock title="Account Details" id="noRec" rendered="{! IF( accountList != null && accountList.size ==0 , true, false)}" >
<apex:outputPanel >
<h1>No Records Found </h1>
</apex:outputPanel>
</apex:pageBlock>
<apex:pageBlock title="Account Details" id="details" rendered="{! IF( accountList != null && accountList.size >0, true, false)}" >
<apex:pageBlockTable value="{!accountList}" var="a">
<apex:column headerValue="Account Name">
<apex:outputLink target="_blank" value="/{!a.id}">{!a.Name}</apex:outputLink>
</apex:column>
<!– If you want facet style you can add like this.
<apex:column >
<apex:facet name="header">Link Name</apex:facet>
<apex:outputLink target="_blank" value="/{!a.id}">{!a.Name}</apex:outputLink>
</apex:column>
–>
<apex:column value="{!a.accountNumber}" headerValue="Account Number"/>
<apex:column value="{!a.Industry}" headerValue="Industry"/>
<apex:column value="{!a.AnnualRevenue}" headerValue="Annual Revenue"/>
<apex:column value="{!a.Phone}" headerValue="Phone"/>
<apex:column value="{!a.website}" headerValue="Web"/>
</apex:pageBlockTable>
<apex:pageblockButtons >
<apex:commandButton value="First Page" rerender="details" action="{!FirstPage}" disabled="{!prev}"/>
<apex:commandButton value="Previous" rerender="details" action="{!previous}" disabled="{!prev}"/>
<apex:commandButton value="Next" rerender="details" action="{!next}" disabled="{!nxt}"/>
<apex:commandButton value="Last Page" rerender="details" action="{!LastPage}" disabled="{!nxt}"/>
</apex:pageblockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>

Here’s the complete github code

36 Replies to “Visualforce Pagination with Dynamic Search”

  1. Hi, Thanks for sharing the code. It helps me a lot. I have a question here. Code that you implemented here does not maintain selected records when you move to next page. Meaning If i am on first page, I select 2 records then I move to next page again select 2 different records and then come back to previous page then it does not maintain selected records state here. Can you please tell me how to maintain selected records state when you move to next page?

    Like

  2. I am getting error on Test class for Previous().
    System.QueryException: SOQL offset must be a non-negative value

    Anyone Facing this issue.Can you please help on this?

    Like

  3. Hi I am facing the issue in pagination …. when clicking on Last page its giving me Offset error that it can return only 2000 Rows .. Please help its Urgent
    How to handle this.. Please

    Like

  4. Hi

    Are there any prerequisites to make this code execute?? Its showing “unexpected token: ‘accountList’ at line 3 column 13”

    Also “Could not resolve the entity from value binding ‘{!acc.Created_From_Date__c}’. can only be used with SObjects, or objects that are Visualforce field component resolvable” though i have created two custom fields by same name.

    Please help me out

    Like

      1. How about this?

        can you tell me did u create the custom field by same name?? if so, in the screenshot its showing as From Date

        Like

        1. Hi
          Am here again.. actually i have written a test class for the same but its covering only 73%

          also if i call previous method its throwing error. Please help me out

          @isTest
          public class ControllerTestClass
          {
          static testMethod void testMethod1()
          {
          Account testAccount = new Account();
          testAccount.Name=’Test Account’ ;
          testAccount.FromDate__c = Date.newInstance(2016, 12, 9);
          insert testAccount;

          Test.StartTest();

          PageReference pageRef = Page.DateAccount; // Add your VF page Name here
          pageRef.getParameters().put(‘id’, String.valueOf(testAccount.Id));
          Test.setCurrentPage(pageRef);

          AccountMultipleSearchWithPagenationCLS1 testAccPlan = new AccountMultipleSearchWithPagenationCLS1();

          testAccPlan.searchAcc();
          //testAccPlan.searchAccounts();
          testAccPlan.FirstPage();
          testAccPlan.next();
          testAccPlan.LastPage();
          testAccPlan.getprev();
          testAccPlan.getnxt();
          //testAccPlan.previous();
          Test.StopTest();
          }
          }

          Like

          1. @Ishwarya: In the test class, can you try to insert more than 10 Account records and then try. Because the page size is 10, the method “Previous” would work fine if the there are at least 11 Account records.

            Like

              1. Hi

                Now its 78% but the date loops and condition.size loop is not getting covered.

                I need to make it 100.Please help me out

                Like

                1. Hi, did you populate the 2 fields Created_To_Date__c and Created_From_Date__c in all the Accounts you created in the test class? If those are populated, the date loops should be covered.

                  Like

                    1. You can add this line

                      testAccPlan.acc = testAccount;

                      below the line AccountMultipleSearchWithPagenationCLS1 testAccPlan = new AccountMultipleSearchWithPagenationCLS1();

                      Like

                    2. To populate the dates, use the below lines for the account

                      testAccount.Created_From_Date__c= Date.newInstance(2016, 12, 9);
                      testAccount.Created_To_Date__c= Date.newInstance(2016, 12, 10);

                      Like

                    3. Hi

                      I have followed ur comments and written below. But though its covering dates when i give previous throwing error

                      @isTest
                      public class ControllerTestClass
                      {
                      static testMethod void testMethod1()
                      {
                      Account testAccount = new Account();
                      testAccount.Name=’Test Account’ ;
                      testAccount.FromDate__c= Date.newInstance(2016, 12, 9);
                      testAccount.ToDate__c= Date.newInstance(2016, 12, 10);
                      insert testAccount;
                      Account testAccount1 = new Account(Name = ‘ttt’);
                      testAccount1.ToDate__c = Date.newInstance(2016, 12, 18);
                      insert testAccount1;
                      Account testAccount2 = new Account(Name = ‘yyy’);
                      insert testAccount2;
                      Account testAccount3 = new Account(Name = ‘q’);
                      insert testAccount3;
                      Account testAccount4 = new Account(Name = ‘c’);
                      insert testAccount4;
                      Account testAccount5 = new Account(Name = ‘yt’);
                      insert testAccount5;
                      Account testAccount6 = new Account(Name = ‘ii’);
                      insert testAccount6;
                      Account testAccount7 = new Account(Name = ‘ui’);
                      insert testAccount7;
                      Account testAccount8 = new Account(Name = ‘yui’);
                      insert testAccount8;
                      Account testAccount9 = new Account(Name = ‘nj’);
                      insert testAccount9;
                      Account testAccount10 = new Account(Name = ‘lo’);
                      insert testAccount10;
                      Test.StartTest();

                      PageReference pageRef = Page.DateAccount;
                      pageRef.getParameters().put(‘id’, String.valueOf(testAccount.Id));
                      Test.setCurrentPage(pageRef);

                      AccountMultipleSearchWithPagenationCLS1 testAccPlan = new AccountMultipleSearchWithPagenationCLS1();
                      testAccPlan.acc = testAccount;
                      testAccPlan.searchAcc();
                      testAccPlan.searchAccounts();
                      testAccPlan.FirstPage();
                      testAccPlan.next();
                      testAccPlan.LastPage();
                      testAccPlan.getprev();
                      testAccPlan.getnxt();
                      testAccPlan.previous();
                      Test.StopTest();
                      }

                      Like

Leave a comment