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?
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:
<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>