[SalesForce] Using nested apex:repeat and pageBlockTable in a page

Well, I couldn't find a way to explain in a simple way my issue (thus the poor title).

I am trying to build a page in which I have to separate some records using two fields on it. One of them is a date, an the other is a relationship. First, I would like to build different tables for each date, and then, on those, I would like to list them by result.

This object, however, can have multiple records for the same line in the table, so I would like to create more columns using apex:repeat.

The logic would be to create a map:

Map<Date, Map<Id, List<CustomObject__c>>>

and then iterate over the date using apex:repeat, then over the Id.

<apex:repeat value="{!myMap}" var="data">
    <apex:pageBlockTable value="{!myMap[data]}" var="emp" id="tableProgramacoes">
        <apex:repeat value="{!myMap[data][emp]}" var="prog">
            <apex:outputText value="{!prog.Field__c}"/>
        </apex:repeat>
    </apex:pageBlockTable>
</apex:repeat>

For what I understand, this would be similar to iterating 3 collections, like:

for (Date data : map.keySet())
{
    for (Id emp : map.get(data).keySet())
    {
        for (CustomObject__c co : map.get(data).get(emp))
        {
            System.debug(co.Field__c);
        }
    }
}

Or this is what I think would work, because even if this compiles, when accessing the page, Salesforce raises an error in the expression of the inner repeater. Is there a way to make this iteration work?

Edit:

Changed code. Still getting errors.
Also thanks Adrian for the nice title!

Best Answer

I had trouble making this work with pageBlockTable (or dataTable) but I could with apex:repeat

Using this controller property with unimaginative accountNames:

public map<Date,List<Account>> dateToAccountsMap {
  get {return new map<Date,List<Account>> {   
    Date.newInstance(2020,1,1) => new List<Account> {new Account(name = 'Account2020-00'),
                                                     new Account(name = 'Account2020-01')},
    Date.newInstance(2021,1,1) => new List<Account> {new Account(name = 'Account2021-00'),
                                                     new Account(name = 'Account2021-01')}

    };
  } 
  private set;
}

and this VF:

<apex:page controller="FooController" >

     <apex:repeat  value="{!dateToAccountsMap}" var="dateKey"> <!-- outer -->            
         <apex:outputText value="{!dateKey}"/>
         <table>
         <apex:repeat value="{!dateToAccountsMap[dateKey]}" var="a"> <!-- inner -->
             <tr><td><apex:outputText value="{!a.name}"/></td></tr>
         </apex:repeat>    
         </table>
     </apex:repeat>
 </apex:page>

I rendered (add your own css styling for the HTML table):

Wed Jan 01 00:00:00 GMT 2020
  Account2020-00
  Account2020-01
Fri Jan 01 00:00:00 GMT 2021
  Account2021-00
  Account2021-01
Related Topic