Search code examples
salesforceapex-codevisualforce

partition a table of Contacts based on a field value in VisualForce


So, Say I have the following visualforce page:

<table width="100%" border="0">
    <tr>  
      <td valign="top">
        <apex:pageBlock mode="edit" id="results">
           <apex:pageBlockTable value="{!contacts}" var="contact">
               <apex:column >
                   <apex:facet name="header">
                         email
                   </apex:facet>
                   <apex:outputField value="{!contact.email}"/>
                 </apex:column>
                  <apex:column >
                   <apex:facet name="header">
                            Name
                       </apex:facet>
                           <apex:commandLink reRender="detail">{!contact.name}
                     <apex:param name="id" value="{!contact.id}"/>
                       </apex:commandLink>
                    </apex:column>
                </td>
           </tr>
      </table>

and the following corresponding controller:

public List<Contact> contacts = [SELECT name, division, email FROM Contact];

Say I want to break up this table on division (i.e, when there is a new division, I would like a header to be placed in the table that reads the division name, and then the names and emails of all contacts within that division to appear under the header... similar ot this:

[                    Division 1                    ]
 Email                                           Name
    ....                                         ...
    ...                                          ...
    ...                                          ...
 [                   Division 2                    ]
  Email                                         Name
  ...                                           ...
 [                   Division 3                    ]
  Email                                        Name
 ...                                             ...

etc...

Is there a way to do this inline in the apex pageblock? Or would I have to make a unique pageblock for each division?

Does anyone have an alternate approach I could take to solve this problem?


Solution

  • It would be much, much easier if your "Division" (custom field?) would be a lookup to a separate object. That's what relationships in Salesforce and this weird syntax in SOQL is there for. You could simply use a subquery and 2 loops:

    [SELECT Name, (SELECT Id, Name, Email FROM Contacts__r) FROM Division__c]
    

    which is similar to

    [SELECT Name, (SELECT Id, Name, Email FROM Contacts) FROM Account]
    

    But I suspect it's a text/picklist field... Then - roughly speaking something like this:

    1. Put results of your select into buckets, 1 bucket for each division
    2. Optionally sort the bucket names (alphabetically?)
    3. In VF - use 2 loops, 1 on buckets, 2nd on the bucket content (it's OK if the 2nd loop will be <apex:pageBlockTable> and not strictly <apex:repeat> etc.)

    Sample (untested!)

    // 1
    Map<String, List<Contact>> contactsByDiv = new Map<String, List<Contact>>();
    for(Contact c: [SELECT Id, Name, Email, Division__c FROM Contact]){
        List<Contact> contactsInThisDiv = contactsByDiv.get(c.Division__c);
        if(contactsInThisDiv.isEmpty()){
            contactsInThisDiv = new List<Contact>{c};
        } else {
            contactsInThisDiv.add(c);
        }
        contactsByDiv.put(c.Division__c, contactsInThisDiv);
    }
    
    // 2
    List<String> allDivisions = new List<String>();
    allDivisions.addAll(contactsByDiv.keyset());
    // I've selected a List to store the Div names because sets are unpredictable. List is easier to sort if you'd want it to
    // allDivisions.sort();
    

    <!-- 3 - in VF page -->
    <apex:repeat value="{!allDivisions}" var="i">
        <h1>{!i}</h1>
        <apex:pageBlockTable value="{!contactsByDiv[i]}" var="c">
            <apex:column value="{!c.Email}" />
        </apex:pageBlockTable>
    </apex:repeat>