Improving our Search functionality by adding paging

In my last post, I showed you how to add “Search” functionality to your related lists. To recap, this is what we built -

[image%255B3%255D.png]

In this post, we will be aiming to make this better, and have it look like this :-

image

Take special note of the two highlighted aspects of this page – the list is showing more columns, has paging built in (next/prev), and also shows you which set of records you are viewing on each page. In the real world, such a basic implementation will have two issues :-
(A) how do I display more columns than just the “name”
(B) how do I implement paging.

To tackle the first problem, you can use the <apex:column> VF construct. This allows you to display a column from the recordset. An example is :-<apex:column value=”{!item.Phone}” />

This displays the “Phone” field for the recordset. Note that the <apex:column> can only be used inside a data set - <apex:dataTable> or <apex:pageBlockTable>.

For  the second problem of paging, we need to take a different approach – we will use a standardSetController to define our set of data. The StandardSetController is a special salesforce class that has a lot of the functionality related to displaying sets of data built-in (paging is one of them, others are saving and updating records in mass, allowing multi-select, control over which page of data to display).

So here’s the code for the Controller. Note what each method/property is doing :-

searchContacts – is the actual method that runs the SOQL query to search contacts
searchResults – a List<Contact> list, that contains the records to be displayed
Next(), Previous(), getHasNext(), getHasPrevious(), getPageRangeText(), getShowPageRangeText() – all related to paging
setController – the set controller

Code Snippet
  1. // create the custom controller extension class
  2. public class Contact_Searcher {
  3.     // Since we are creating an extension to the account standard controller,
  4.     // create an account object to hold the current account
  5.     Account a;
  6.    
  7.     public Contact_Searcher(ApexPages.StandardController controller)
  8.     {
  9.         // Get the current account, and store it in the account object
  10.         a = (Account) controller.getRecord();
  11.     }
  12.    
  13.     public string searchValue
  14.     {
  15.         get
  16.         {
  17.             if(searchValue == null)
  18.                 searchValue = '';
  19.             return searchValue;
  20.         }
  21.         set;
  22.     }
  23.    
  24.     public List<Contact> searchResults
  25.     {
  26.         get
  27.         {
  28.             return (List<Contact>)setController.getRecords();
  29.         }
  30.         set;
  31.     }
  32.    
  33.     public Boolean renderTable
  34.     {
  35.         get
  36.         {
  37.             if(renderTable == null)
  38.                 return false;
  39.             return renderTable;
  40.         }
  41.         set;
  42.     }
  43.    
  44.     public void Next()
  45.     {
  46.         setController.Next();
  47.     }
  48.    
  49.     public void Previous()
  50.     {
  51.         setController.Previous();
  52.     }
  53.  
  54.     public ApexPages.StandardSetController setController
  55.     {
  56.         get
  57.         {
  58.             if(searchValue == '')
  59.             {
  60.                 List<Contact> contactList = new List<Contact>();
  61.                 return new ApexPages.StandardSetController(contactList);
  62.             }
  63.             else
  64.                 return setController;
  65.         }
  66.         set;
  67.     }
  68.    
  69.     public Boolean getHasNext()
  70.     {
  71.         if(setController==null)
  72.             return false;
  73.         return setcontroller.getHasNext();
  74.     }
  75.  
  76.     public Boolean getHasPrevious()
  77.     {
  78.         if(setController==null)
  79.             return false;       
  80.         return setcontroller.getHasPrevious();
  81.     }
  82.    
  83.     public String getPageRangeText()
  84.     {
  85.         if(setController == null)
  86.             return '';
  87.         else
  88.         {
  89.             Integer startP = ((setController.getPageNumber() - 1) * setController.getPageSize()) + 1;
  90.             Integer endP;
  91.             if(setController.getPageNumber()*setController.getPageSize() > setcontroller.getResultSize())
  92.                 endP = setcontroller.getResultSize();
  93.             else
  94.                 endP = setController.getPageNumber()*setController.getPageSize();
  95.             return 'Showing Records : ' + startP + ' - ' + endP + ' of total ' + setcontroller.getResultSize();
  96.         }
  97.     }
  98.    
  99.  
  100.     public Boolean getShowPageRangeText()
  101.     {
  102.         if (setController==null)
  103.             return false;       
  104.         if(setcontroller.getResultSize() > 0)
  105.             return true;
  106.         else
  107.             return false;
  108.     }   
  109.    
  110.     public void searchContacts()
  111.     {
  112.         String finalSearchValue = '%' + searchValue + '%';
  113.         List<Contact> contactList = new List<Contact>([select Id, Name, Title, Department, Phone, Email from Contact where Account.Id = :ApexPages.CurrentPage().getParameters().get('Id')
  114.                     and Name like :finalSearchValue]);
  115.         setController = new ApexPages.StandardSetController(contactList); 
  116.         setController.setPageSize(3);
  117.         renderTable = true;
  118.     }
  119. }

And here is the Visualforce page :-

Code Snippet
  1. <apex:page standardController="Account" extensions="Contact_Searcher">
  2. <apex:form >
  3.     <apex:pageBlock title="Contact Search">
  4.         <!--I got the <h2> tag with the CSS name by viewing the source of my salesforce page
  5.         Another neat thing to note is the use of &nbsp; to add a white space -->
  6.         <h2 class="maintitle">Enter Search String&nbsp;&nbsp;</h2>
  7.         <apex:inputText id="searchBox" value="{!searchValue}" />
  8.         <apex:commandButton id="submit" value="Search" action="{!searchContacts}" />
  9.     </apex:pageBlock>
  10.         <apex:pageBlock title="Search Results">
  11.             <apex:pageBlockTable value="{!searchResults}" var="c" rendered="{!renderTable}">
  12.                 <apex:column value="{!c.Name}" />
  13.                 <apex:column value="{!c.Title}" />
  14.                 <apex:column value="{!c.Department}" />
  15.                 <apex:column value="{!c.Phone}" headerValue="Phone No." />
  16.                 <apex:column value="{!c.Email}" headerValue="Email Address" />
  17.             </apex:pageBlockTable>
  18.         </apex:pageBlock>
  19.     <apex:commandButton id="btnPrev" value="Prev" action="{!Previous}" rendered="{!HasPrevious}" />
  20.     <apex:commandButton id="btnNext" value="Next" action="{!Next}" rendered="{!HasNext}" />
  21.     <br />
  22.     <br />
  23.     <apex:outputLabel id="opPageRangeText" styleClass="brandTertiaryBgr pbSubheader tertiaryPalette" rendered="{!ShowPageRangeText}" value="{!PageRangeText}" />
  24. </apex:form>
  25. </apex:page>

Run this code in your instance, and you’ve now got nice functionality on your related lists. Yes, you can re-use the same code for different types of standard and custom objects (some modifications will be required, especially to the SOQL query).

No comments:

Post a Comment