Sunday, December 28, 2014

Custom Controller Pagination with dynamic search.

Custom Controller Pagination with dynamic search in Visualforce page.


Hi,

In this post i am going to give a small example on how to use dynamic search in visualforce with pagination using custom controller.


For this once the user enter his search criteria and click on search button the page is going to populate account details with Pagination of (Next,Previous,Last etc..). To achieve this i am using custom controller instead of Standared Set Controller.


Pagination in Visualforce



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>


Controller Class:

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;
}
}


}



Example 2: 


In this example i am not using any buttons simple using command links move forward or backward directions and also displaying the count of records, page numbers etc..




VF Page:
<apex:page controller="CustomPaginationVFController">
          
    <apex:form >
                
        <apex:pageBlock title="VF Sample Custom Pagination Example" id="mpb">
        
            <!-- next, previous and page info -->
            <apex:commandLink action="{!doPrevious}" rendered="{!hasPrevious}" value="Previous" />
            <apex:outputLabel rendered="{!NOT(hasPrevious)}" value="Previous" />
            
            <apex:outputLabel value=" (page {!page} of {!totalPages}) | showing {!startIdx} to {!endIdx} of {!totalRecords} " />
            
            <apex:commandLink action="{!doNext}" rendered="{!hasNext}" value="Next" />
            <apex:outputLabel rendered="{!NOT(hasNext)}" value="Next" />
            
            <br/>
            
            <!-- table of data -->
            <apex:pageBlockTable title="Contacts" value="{!tRecords}" var="c">
                <apex:column >
                    <apex:facet name="header">Action</apex:facet>
                    <apex:inputCheckbox value="{!c.IsSelected}" />
                </apex:column>
                <apex:column value="{!c.tContact.FirstName}"/>
                <apex:column value="{!c.tContact.LastName}"/>
                <apex:column value="{!c.tContact.Title}"/>
                <apex:column value="{!c.tContact.Phone}"/>
                <apex:column value="{!c.tContact.Email}"/>
            </apex:pageBlockTable>
        
            <br/>
            
            <!-- next, previous and page info -->
            <apex:commandLink action="{!doPrevious}" rendered="{!hasPrevious}" value="Previous" />
            <apex:outputLabel rendered="{!NOT(hasPrevious)}" value="Previous" />
            
            <apex:outputLabel value=" (page {!page} of {!totalPages}) | showing {!startIdx} to {!endIdx} of {!totalRecords} " />
            
            <apex:commandLink action="{!doNext}" rendered="{!hasNext}" value="Next" />
            <apex:outputLabel rendered="{!NOT(hasNext)}" value="Next" />
            
        
        </apex:pageBlock> 
        
    </apex:form>



</apex:page>


Controller Class:


public with sharing class CustomPaginationVFController {

    //default page size
    private static final Integer PAGE_SIZE = 10;
    
    
    //pagination information
    public Integer page{get;set;}
    public Integer totalRecords{get;set;}
    public Integer totalPages{get;set;}
    public Integer startIdx{get;set;}
    public Integer endIdx{get;set;}
    
    

    /*
    *   set controller
    */
    public List<CCWRow> tRecords{get;set;}
    
    
    
    /*
    *   constructor
    */
    public CustomPaginationVFController ()
    {
        //init variable
        this.tRecords = new List<CCWRow>();
        
        //set initial page
        this.page = 1;
        
        //load records
        getContacts();
                
    }
    
    
    /*
    *   advance to next page
    */
    public void doNext(){
        
        if(getHasNext()){
            this.page++;
            getContacts();
        }

    }
    
    
    /*
    *   advance to previous page
    */
    public void doPrevious(){
        
        if(getHasPrevious()){
            this.page--;
            getContacts();
        }
                
    }
    
    /*
    *   returns whether the previous page exists
    */
    public Boolean getHasPrevious(){
        if(this.page>1){
            return true;
        }
        else{
            return false;
        }
    }
    
    /*
    *   returns whether the next page exists
    */
    public Boolean getHasNext(){
        if(this.page<this.totalPages){
            return true;
        }
        else{
            return false;
        }
    }
    
    
    
    /*
    *   return current page of records
    */
    public void getContacts(){
        
        //calculate range of records for capture
        this.startIdx = (this.page-1)*PAGE_SIZE;
        this.endIdx = this.page*PAGE_SIZE;
        this.totalRecords = 0;
        
        //clear container for records displayed
        this.tRecords.clear();
                
        
        //cycle through
        for(Contact c : [SELECT Id, FirstName, LastName, Title, Phone, MobilePhone, Email, 
                            MailingStreet, MailingState, MailingPostalCode, MailingCountry, MailingCity 
                            FROM Contact 
                            ORDER BY LastName ASC 
                            LIMIT 50000]){
        
            //capture records within the target range
            if(this.totalRecords>=this.startIdx && this.totalRecords<this.endIdx){   
           
                this.tRecords.add( new CCWRow(c, false) );
            }
            
            //count the total number of records
            this.totalRecords++;
        
        }
        
        
        //calculate total pages
        Decimal pages = Decimal.valueOf(this.totalRecords);
        pages = pages.divide(Decimal.valueOf(PAGE_SIZE), 2);
        this.totalPages = (Integer)pages.round(System.RoundingMode.CEILING);
        
        //adjust start index e.g. 1, 11, 21, 31
        this.startIdx++;
        
        
        //adjust end index
        if(this.endIdx>this.totalRecords){
            this.endIdx = this.totalRecords;
        }
     
        
        //display resource usage
        System.Debug(LoggingLevel.WARN,'****** LIMIT query rows: '+Limits.getQueryRows()+' / '+Limits.getLimitQueryRows());
        System.Debug(LoggingLevel.WARN,'****** LIMIT heap size: '+Limits.getHeapSize()+' / '+Limits.getLimitHeapSize());
        System.Debug(LoggingLevel.WARN,'****** LIMIT cpu time: '+Limits.getCpuTime()+' / '+Limits.getLimitCpuTime());
       // System.Debug(LoggingLevel.WARN,'****** LIMIT script statements: '+Limits.getScriptStatements()+' / '+Limits.getLimitScriptStatements());
        
    }
        
    
    /*
    *   helper class that represents a row
    */
    public with sharing class CCWRow{
        
        public Contact tContact{get;set;}
        public Boolean IsSelected{get;set;}
        
        public CCWRow(Contact c, Boolean s){
            this.tContact=c;
            this.IsSelected=s;
        }
        
    } 

}



Enjoy the coding......





20 comments:

Anonymous said...

Code issues in this. The navigation buttons are always disabled even when the totalRecs size is greater than the LimitSize too!

Unknown said...

very nice article keep posting salesforce training

Unknown said...

thanks for your collective information on Salesforce Tutorial Training

Unknown said...

Can we Combine both functionalities ?
Dynamic search and editing of selected records ?

Data science said...

Thanks for sharing a good information about salesforce . .......This article is very useful to learners. Sales force online training

Unknown said...

nice tutorials..thanks for sharing such a wonderful information..keep update with your blogs.

SalesForce online course

Unknown said...

Interesting article! Thank you for sharing
https://onlineitguru.com/salesforce-online-training-placement.html

Unknown said...

nice blog SalesForce Online Training

fally jonesh said...

I can set up my new idea from this post. It gives in depth information. Thanks for this valuable information for all,..
War Wings Flip Master Happy Room 2

Unknown said...

brilliant

IMS said...

Thank you so much. It saved me lot of time.

Unknown said...

very helpful..thanks

radha said...

Nice post.Keep sharing salesforce Online Training

akhilapriya404 said...

Thanks for posting such a great article.you done a great job salesforce Online Training

candy lol said...

It really is truly complicated to see out this type of fantastic articles with a few useful data and facts
Videodownloaderfb.com

nick jones said...

good blog..
Server and Storage Solutions

akhilapriya404 said...

This is one awesome blog article. Much thanks again salesforce training

The code Codex said...

This logic only works for 50k records What if WE have million records??
Please help..............

The code Codex said...

This logic only works for 50k records What if WE have million records??
Please help..............

Jones said...

You need personal informations from companies,family and friends that will better your life and you need easy access without them noticing just contact james or you’re financially unstable or you have a bad credit score, he will solve that without stress,he and his team can clear criminal records without leaving a trace and can also anonymously credit your empty credit cards with funds you need,all these are not done free obviously but I like working with James and his team cause they keep you updated on every step taken in order to achieve the goal and they also deliver on time,I tested and confirmed this I’m still happy on how my life is improving after my encounter with him ,you can send a mail to premiumhackservices@gmail.com

Post a Comment

 
| ,