Creating A Visualforce Table with Sorting and Pagination

All of the standard lists in Salesforce have the ability to sort and paginate. However, when you create a table in Visualforce, it’s not that easy to add sorting or pagination on it. For pagination, there is 'StandardSetController' which helps when implementing pagination for a list of standard 'sObjects'. Unfortunately, there isn’t a simple solution for custom objects.

We’ve created a common component for ourselves that implements pagination and sorting and allows the user to change the number of rows in each page. We made it so it’s easy to use on every list of objects.

 

The way it works is that each list of objects you would like to display in the list you will need to create a wrapper class for it. We created a base wrapper class so it’s easy to create a new wrapper class in the future:

<code class="rainbow" data-language="java">public class AccountWrapper extends PaginationTableObjectWrapper { public String Name {get; private set;} public String Phone {get; private set;} public AccountWrapper (Account acc){ this.Name = acc.Name; this.Phone = acc.Phone; if (this.Phone == null) { this.Phone = ''; } populateFields(); } public override Integer compareTo(Object compareTo){ AccountWrapper otherAccountWrapper = (AccountWrapper) compareTo; Integer directionMultiplier = (sortDirection == 'ASC') ? 1 : -1; if(sortByField == 'Name'){ return this.Name.compareTo(otherAccountWrapper.Name)*directionMultiplier; } else if(sortByField == 'Phone'){ return this.Phone.compareTo(otherAccountWrapper.Phone)*directionMultiplier; } return 0; } private void populateFields() { fieldsList = new List<paginationtableobjectwrapper.fieldwrapper>(); fieldsList.add(new PaginationTableObjectWrapper.FieldWrapper('Name', this.Name)); fieldsList.add(new PaginationTableObjectWrapper.FieldWrapper('Phone', this.Phone)); } }</paginationtableobjectwrapper.fieldwrapper></code>

 

The wrapper class would be able to tell how to sort the objects based on each column by implementing the 'compareTo' method.

In our example, we’re creating a table of accounts and allowing the user to sort the table by each of the 'Name' and 'Phone' columns. Our page controller would query all of the accounts that we would like to display and create a wrapper instance for each of them.

<code class="rainbow" data-language="java"><span class="keyword">public</span> <span class="keyword">class</span> <span class="entity class">PaginationExampleController</span> { <span class="keyword">public</span> <span class="entity class">List</span><span class="operator"><</span><span class="entity class">PaginationTableObjectWrapper</span><span class="operator">></span> wrappers {get; set;} <span class="keyword">public</span> <span class="entity class">Integer</span> pageSize {get; set;} <span class="keyword">public</span> <span class="entity function">PaginationExampleController</span>() { pageSize <span class="operator">=</span> <span class="integer">5</span>; wrappers <span class="operator">=</span> <span class="keyword">new</span> <span class="entity function">List<accountwrapper></accountwrapper></span>(); <span class="entity class">List</span><span class="operator"><</span><span class="entity class">Account</span><span class="operator">></span> all_accounts <span class="operator">=</span> [<span class="constant">SELECT</span> <span class="entity class">Name</span>, <span class="entity class">Phone</span>, <span class="entity class">Id</span> <span class="constant">FROM</span> <span class="entity class">Account</span> <span class="constant">LIMIT</span> <span class="integer">1000</span>]; <span class="entity function">for</span>(<span class="entity class">Account</span> acc <span class="operator">:</span> all_accounts){ wrappers.<span class="entity function">add</span>(<span class="keyword">new</span> <span class="entity function">AccountWrapper</span>(acc)); } } }</code>

 

Then all our Visualforce page needs to do is call our Paginator component to generate the table and that’s it! We need to pass to the Visualforce component the list of wrapper instances and the default size of every page.

<code class="rainbow" data-language="html"><span class="support tag"><span class="support tag"><</span><span class="support tag-name">apex</span></span>:page <span class="support attribute">controller</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">PaginationExampleController</span><span class="string quote">"</span><span class="support tag close">></span> <span class="support tag"><span class="support tag"><</span><span class="support tag-name">apex</span></span>:form <span class="support tag close">></span> <span class="support tag"><span class="support tag"><</span><span class="support tag-name">apex</span></span>:pageBlock <span class="support tag close">></span> <span class="support tag"><span class="support tag"><</span><span class="support tag-name">c</span></span>:Paginator <span class="support attribute">Records</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">{!wrappers}</span><span class="string quote">"</span> <span class="support attribute">PageLength</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">{!pageSize}</span><span class="string quote">"</span><span class="support tag close">/></span> <span class="support tag"><span class="support tag"><</span><span class="support tag special">/</span><span class="support tag-name">apex</span></span>:pageBlock<span class="support tag close">></span> <span class="support tag"><span class="support tag"><</span><span class="support tag special">/</span><span class="support tag-name">apex</span></span>:form<span class="support tag close">></span> <span class="support tag"><span class="support tag"><</span><span class="support tag special">/</span><span class="su

 

This works with a common component we have called Paginator and we can use it for every table we would like to have sorting and pagination in it.


The Paginator component has a controller called PaginatorController. All of the logic for the pagination is held in our PaginatorController class, this class has hold list of wrapper classes, the pagination methods and the sorting method. Another class that we have created is the base class of the wrapper class called PaginationTableObjectWrapper.

You can check out the code for those classes with the test classes in our GitHub.