Wednesday 27 October 2010

VisualForce Conditional List Rendering

This week I've been building VisualForce pages for an external site.  I had a number of different sobject lists scattered over the pages and I found myself adding property after property to my controller to avoid rendering empty lists.

I decided there had to be a better way to do this, so spent some time write a component that would take a list of sobjects, a title and some styling and only produce output of the list contained at least one element. So if there is data the list appears:


But if the list is empty, neither it nor its title appear:




The component appears in the page as follows:

<c:ListIterator list="{!accounts}" var="acc" title="Accounts" titleStyle="font-weight:bold">
   <p>
 > {!acc.Name} : {!acc.BillingStreet}
   </p> 
</c:ListIterator>

So the idea is that I have a list of accounts that I want to iterate and display an entry of the form 
"> My Account : My Street" for each one.

Below is my custom component.
<apex:component controller="ListIteratorController">
  <apex:attribute name="list" type="SObject[]" description="The list to iterate" assignTo="{!values}" />
  <apex:attribute name="title" type="String" description="The list title" />
  <apex:attribute name="titleStyleClass" type="String" description="The styleclass for the title" />
  <apex:attribute name="titleStyle" type="String" description="The inline style for the title" />
  <apex:attribute name="var" type="String" description="Variable representing an element in the list" />
  
  <apex:outputPanel rendered="{!render}">
      <apex:outputText value="{!title}" style="{!titleStyle}" styleClass="{!titleStyleClass}"/>
     <apex:repeat value="{!list}" var="ele">
    <apex:componentBody >
     <apex:variable var="{!var}" value="{!ele}"/>
      </apex:componentBody>
     </apex:repeat>
  </apex:outputPanel>
  
</apex:component>


The important section is:
<apex:repeat value="{!list}" var="ele">
 <apex:componentbody>
  <apex:variable value="{!ele}" var="{!var}">
 </apex:variable></apex:componentbody>
</apex:repeat>

This iterates the list of sobjects passed in as an attribute, and then pulls in the page markup that was enclosed by the <c:ListIterator> component.  The <apex:variable> tag allows the current element from the list to be used as a replacement in the page markup.

The custom controller associated with the component simply provides storage for the list that is being iterated and a method to determine if the list should be rendered (i.e. is not empty).

The component, page and controllers can be downloaded hereSimply unzip into the src directory of your Force.com project in the IDE.