Multi-row: Paging using StandardSetController - El Toro - Find articles about Visualforce, Apex, Force.com and Salesforce in general

Print Preview

Multi-row: Paging using StandardSetController

This sample is one of the many multi-row demos you will find on this site. In this case, I want to demonstrate few techniques:

  • Building a paging sytem using the ApexPages.StandardSetController.
  • Show the different methods available to go to the first, previous, next and last pages.
  • Two ways to instantiate the standard set controller, using a SOQL query and using a SOSL search
This is what the code will display:

This is the Visualforce page:

<apex:page controller="multiRow" tabStyle="Contact">
    <apex:form id="accountForm" > 
        <apex:pageMessages /> 
        <apex:pageBlock title="Search Results" > 
            <apex:pageBlockButtons >
                <apex:outputPanel rendered="{!totalPages > 1}" >
                    <table border="0" style="width:100%; text-align: right">
                        <tr>
                            <td style="width:100%">&nbsp;</td>
                            <td style="vertical-align: middle">
                                <apex:actionStatus id="statusPaging">
                                    <apex:facet name="start">
                                        <apex:outputPanel >Please wait...</apex:outputPanel> 
                                    </apex:facet>
                                    <apex:facet name="stop" />
                                </apex:actionStatus>
                            </td>
                            <td style="text-align: center; white-space: nowrap">
                                <b>Page:</b><br/>{!contactsSetController.PageNumber} of {!totalPages}
                            </td>
                            <td style="vertical-align: middle">
                                <apex:commandButton value="|<" action="{!contactsSetController.First}"
                                disabled="{!Not(contactsSetController.HasPrevious)}" rerender="accountForm" status="statusPaging"/>
                            </td>
                            <td style="vertical-align: middle">
                                <apex:commandButton value="<" action="{!contactsSetController.Previous}"
                                disabled="{!Not(contactsSetController.HasPrevious)}" rerender="accountForm" status="statusPaging"/>
                            </td>
                            <td style="vertical-align: middle">
                                <apex:commandButton value=">" action="{!contactsSetController.Next}"
                                disabled="{!Not(contactsSetController.HasNext)}" rerender="accountForm" status="statusPaging"/>
                            </td>
                            <td style="vertical-align: middle">
                                <apex:commandButton value=">|" action="{!contactsSetController.Last}"
                                disabled="{!Not(contactsSetController.HasNext)}" rerender="accountForm" status="statusPaging"/>
                            </td>
                        </tr>
                    </table>
                </apex:outputPanel>  
            </apex:pageBlockButtons> 
  
            <apex:pageBlockTable value="{!Contacts}" var="contact" > 
                <apex:column headerValue="Name"> 
                    <apex:outputLink value="/{!contact.id}" id="contactLink">{!contact.name}</apex:outputLink> 
                </apex:column> 
                <apex:column value="{!contact.FirstName}"/> 
                <apex:column value="{!contact.LastName}"/> 
            </apex:pageBlockTable> 
        </apex:pageBlock> 
    </apex:form> 
</apex:page>

This is the Apex custom controller:

public class multiRow {
    public Integer totalPages { get; set; }  
    public ApexPages.StandardSetController contactsSetController { get; set; }
    public List<Contact> Contacts {
        get {
            return (List<Contact>) contactsSetController.getRecords();
        }
    } 

    public multiRow () {
        Decimal dtotalPages;
        Integer iRecordsPerPage = 5; 
        Database.QueryLocator qLoc;
        
        // You can initialize the set controller using a SOQL query:
        qLoc = Database.getQueryLocator([Select Id, Name, AccountId, FirstName, LastName From Contact c]);
        contactsSetController = new ApexPages.StandardSetController(qLoc);
        
        // Or with a list of records, which is useful for SOSL searches or if you already have the records in a list.
        // List<Sobject> lContacts = [FIND 'smith*' IN ALL FIELDS RETURNING Contact (Id, Name, AccountId, FirstName, LastName )][0];
        // contactsSetController = new ApexPages.StandardSetController(lContacts);
        
        // Create the set controller

        // Set the number of records to be displayed per page and calculate the number of pages.
        contactsSetController.setPageSize(iRecordsPerPage);
        dtotalPages = (contactsSetController.getResultSize() / contactsSetController.getPageSize());
        dtotalPages = Math.floor(dtotalPages) + ((Math.mod(contactsSetController.getResultSize(), iRecordsPerPage)>0) ? 1 : 0);
        totalPages = Integer.valueOf(dtotalPages);
    }
}

Note that if you want to have Salesforce build the Standard Set controller, you would not need to change much form the visualforce page size, except for the page definition like this:

<apex:page standardController="Contact" recordSetVar="contacts" extensions="multiRow">
<!-- Everything else is identical to the previous sample -->
</apex:page>

And you would have to make some bigger changes in the apex code, specifically simplifying it since it does not need to create the Standard controller, but work with the one that was provided in the constructor. The code would look like this:

public class multiRow {
    public Integer totalPages { get; set; }  
    public ApexPages.StandardSetController contactsSetController { get; set; }
    public List<Contact> Contacts {
        get {
            return (List<Contact>) contactsSetController.getRecords();
        }
    } 

    public multiRow(ApexPages.StandardSetController controller) {
        Decimal dtotalPages;
        Integer iRecordsPerPage = 5; 

        // do not create a controller, but take the one you are receiving...
        contactsSetController = controller;
        
        // Set the number of records to be displayed per page and calculate the number of pages.
        contactsSetController.setPageSize(iRecordsPerPage);
        dtotalPages = (contactsSetController.getResultSize() / contactsSetController.getPageSize());
        dtotalPages = Math.floor(dtotalPages) + ((Math.mod(contactsSetController.getResultSize(), iRecordsPerPage)>0) ? 1 : 0);
        totalPages = Integer.valueOf(dtotalPages);
    }
}

Then you could invoke the page using an URLĀ like this:

https://c.na6.visual.force.com/apex/multirow?fcf=00B800000065fK0

Where the IDĀ corresponds to one of the List Views you have defined, or if you prefer this page could be associated to a list button.

comments powered by Disqus

© El Toro . IT @ 2013
Andrés Pérez