Advanced VisualForce Lists

January 23, 2013 Appirio

 by Will Supinski (@dumbfire)
Salesforce provides excellent tools for developers to build tables or lists in custom pages with very little code.  However, requirements often dictate more complex list functionality such as displaying only 5 or 10 records at a time with pagination or displaying data from several unrelated objects in a single table!  To solve the above use-cases one should turn to using StandardSetControllers for pagination and an apex design pattern called wrapper classes for multi-object handling.
Salesforce provides some cool apex for handling pagination of large lists called the StandardSetController.  One of the benefits of this is that there is no need to use javascript for this solution.  To use this there are a couple of key lines of apex code to review:

StandardSetController Accounts = new ApexPages.StandardSetController(Database.getQueryLocator(
[Select Id, Name FROM Account Order By Name limit 100]));

This code essentially wraps a query result in StandardSetController which allows the user to control what section of the results is displayed on the page.  For instance, you can restrict the table results down to 5 and then provide a next button to load the next 5 results as seen below:

An apex design pattern called wrapper classes can be used to display additional information in a visualforce table that is not available in the data model.  This can include data from multiple objects or simple data that is generated in memory through some calculation or logic.  Wrapper classes are inner classes added to your controller with member variables that store the information needed to display on the list as below:

//Wrapper Class for usage in the visualforce list
   public class ListWrapper
   {
    //variables for data display
    public String Acc  {get;set;}
    public String Cont {get;set;}
    public String Opp  {get;set;}
   
    //constructor for handling data imputs from various object types
    public ListWrapper(Account act, Opportunity o, Contact c)
    {
    if(act != null)
     Acc = act.Name;
    if(c != null)
     Cont = c.Name;
    if(o != null)
     Opp = o.Name;
    }
   }

The data is queried and then “wrapped” in the wrapper classes.  Note, this example code is using Accounts, Opportunities, and Contacts which are all related objects and may not need the use of wrapper classes since a complex query could be used instead.  However, for the ease of code readability and portability this code uses them as below:

List wrappers = new List();

           if(data == null)
           {
            //Query unrelated objects into list.
            List accountList = [Select Id, Name FROM Account Order By Name];
            List oppList = [Select Id, Name FROM Opportunity Order By Name];
            List contList    = [Select Id, Name FROM Contact Order By Name];
        
         //create a wrapper for the data to display
            integer i = 0;
            for(Account a: accountList)
            {
            Opportunity opp;
            Contact cont;
           
            if(oppList.size() > i )
             opp = oppList.get(i);
           
            if(contList.size() > i)
             cont = contList.get(i);
           
            ListWrapper lw = new ListWrapper(a, opp, cont);
            wrappers.add(lw);
            i++;
            }
}
           return wrappers; 

 
The wrapper classes are then iterated over (via the Data variable) in the visualforce instead of the object itself:
>
      

         

           Account

          
   

         

           Contact

         

         

           Opportunity

          
 

        
  

Thus, the above code can render a table as seen here:

The above wrapper classes and StandardSetController paradigms can be combined to create even more complex visualforce tables!

Previous Article
Workday Technology Highlights of 2012
Workday Technology Highlights of 2012

by Lori Asburry  As consultants, we spend a great deal of time each quarter helping customers stay current ...

Next Article
Development Lifecycle with Force.com and Git
Development Lifecycle with Force.com and Git

by Geoff Escandon gescandon@appirio.comDevelopment in the Cloud is rapidly becoming an bazaar of languages ...