1

I am trying to use a data map to display information in a visualforce table. I have tried many of the suggestions in similar questions but no luck yet. My relevant controller code follows:

Public Map<User,List<List<ForecastValues>>> DirectReportValueMap{ get; set; }
public class forecastItems{
    public List<OpportunityLineItem> all { get; set; }
    public List<OpportunityLineItem> noSchedule { get; set; }
    public List<OpportunityLineItemSchedule> schedule { get; set;}
}

Public static forecastItems initializeForecastItems(){ 
        forecastItems fi = new forecastItems();
        fi.all = new List<OpportunityLineItem>();
        fi.noSchedule = new List<OpportunityLineItem>();
        fi.schedule = new List<OpportunityLineItemSchedule>();
        return fi;
    }
Public static forecastValues initializeForecastValues(){
        forecastValues fv = new forecastValues();
        fv.quantity = 0; fv.revenue = 0;
        return fv;
    }
Public List<forecastValues> initializeforecastCategValues(){
        forecastCategValues = new forecastValues[5]; /// one for each category: closed, commit, bestCase, Pipeline, TOTALS \\\
        for (integer i = 0; i < forecastCategValues.size(); i++){
            forecastCategValues[i] = initializeForecastValues();
        }
        return forecastCategValues;
    }
 Public List<List<forecastValues>> initializemonthlyValues(){
        List<List<ForecastValues>> mV = new List<List<ForecastValues>>();
        for (integer i = 0; i < 6; i++){ /// one for each period in forecasting range: 1-6 \\\
            mV.add(initializeforecastCategValues());
        }
        return mV;
    }


Public void UpdatePage(){
    directReports = [SELECT Id, Name, UserRole.Name FROM User WHERE Id IN :directReportIds];
        for(User u:directReports){
            List<List<ForecastValues>> dRMonthlyValues = initializemonthlyValues();
            forecastItems drForecastItems = initializeForecastItems();
            drForecastItems.all = DirectReportLIMap.get(u.Id);
            drForecastItems = splitForecastItemsbySchedule(drForecastItems);
            dRMonthlyValues = GetForecastValues(drForecastItems);
            DirectReportValueMap.put(u,dRMonthlyValues);
        }
System.debug(DirectReportValueMap);
}

I am trying to display the DirectReportValueMap, where the user name is in one column and each value in the List> is shown in the following column (I'm not too concerned about styling at this point, I just would like to see it displayed.) I have used system.debug(DirectReportValueMap) to ensure that the map is filled correctly.

I have tried using the following visualforce code to display the data, but it doesn't display anything.

    <apex:outputPanel>
    <apex:repeat value="{!DirectReportValueMap}" var="key" >
            <apex:pageBlock>
                <apex:outputText value="{!key.Name}" />
                <apex:pageBlockTable value="{!DirectReportValueMap[key]}" var="valueList" >
                    <apex:column value="{!valueList}"/>
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:repeat>
    </apex:outputPanel>

Does anyone have and advice how to make this work? I am stumped!

for context, I am basically rewriting the built-in 'Customizable Forecast' tab, where at this point in my page I am collecting the current users direct reports as the map keys and calculating their individual forecast data per month. I chose to use a map so I can pass the entire mess of data from one function to another. Also, I was hoping that a map would allow me to display all of this information in a single nested table. Since the number of direct reports varies by user, I'm not sure how to initialize the right number of public lists to be able to access in my VF page

  • If you make your Visualforce page just <apex:repeat value="{!DirectReportValueMap}" var="key" >{!key.name},</apex:repeat> does it output a comma delimited list of the users? – caleb.breckon Dec 18 '17 at 19:22
  • Unfortunately, no. Not sure if it matters, but its on a tab panel. When I put your piece inside a pageBlock, even the block doesn't show on the tab. – laurspellm Dec 18 '17 at 19:35
  • Probably worth refactoring your data into separate lists to avoid this complexity.. you're going to need multiple apex:repeat's in order to access the lowest level list – battery.cord Dec 18 '17 at 19:39
  • what displays with just <apex:page controller="ControllerName">{!DirectReportValueMap}</apex:page> ? – caleb.breckon Dec 18 '17 at 19:40
  • Also, any reason you're using a Map for that top level instead of List? There's not any .get() in your posted code. – caleb.breckon Dec 18 '17 at 19:41
3

Using a dummy data class, I wrote a mockup of how to access multi-leveled list or map variables.

The basic issue with your code is that you need to loop an additional time, to access the lists inside your list of lists. Multiple repeats using your list structure is demonstrated below.

The complex issue is that your data seems to be poorly organized, and could use optimization, which would in turn make your visualforce code simpler. Instead of the second list, maybe something such as Map<User, Map<String, Forecast>>, with the strings being the forecast stages?

Test Page

<apex:page controller="TestClass">
    <apex:pageBlock title="Nodes">
        <apex:repeat value="{!KeySet}" var="Key">
            <apex:repeat value="{!NodeMap[Key]}" var="listOfLists" >
                <apex:pageBlockTable value="{!listOfLists}" var="listOfNodes">
                        <apex:column value="{!Key}" headerValue="Key" />
                        <apex:column headerValue="Value">
                            <apex:repeat value="{!listOfNodes}" var="node">
                                <apex:outputText>{!node.Value}</apex:outputText>
                            </apex:repeat>
                        </apex:column>                  
                </apex:pageBlockTable>
            </apex:repeat>
        </apex:repeat>
    </apex:pageBlock>
</apex:page>

Test Class

public class TestClass {

    public Map<String, List<List<Node>>> NodeMap { get; set; }

    public TestClass() {
        NodeMap = new Map<String, List<List<Node>>>(); 

        NodeMap.put('First', new List<List<Node>>{
                new List<Node>{ new Node('Test'), new Node('Test2') },
                new List<Node>{ new Node('Test3'), new Node('Test4') }
        }); 

        NodeMap.put('Second', new List<List<Node>>{
                new List<Node>{ new Node('Test5'), new Node('Test6') },
                new List<Node>{ new Node('Test7'), new Node('Test8') }
        }); 
    }

    public List<String> KeySet {
        get {
            return new List<String>(NodeMap.keySet()); 
        }
    }

    public class Node {
        public Object Value { get; set; }

        public Node(Object Value) {
            this.Value = Value; 
        }
    }
}

Output

enter image description here

  • Great, I really appreciate you taking the time to create this example. I love the idea of a map of maps for organization, I didn't know that was possible and would really help my complexity issue. Thank you!! – laurspellm Dec 18 '17 at 20:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.