function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
mattomatto 

Unable to pass or see var in apex:repeat ?

I am writing a Visualforce page to show commission payments for our company's sales reps.  The commissions have gotten more complicated as we implemented a team/pod environment.  At a high level, this means some sales reps may earn commissions on opportunities owned by other reps on their team, and the commission split varies by opportunity record type.  This appeared to be too complicated to accomplish in a standard report, and developing a simple Visualforce page seemed like an alternative solution.

 

My approach for the page is to have a string list with all of the sales rep names.  In the future, this may be queried dynamically, for the moment it is hard coded.  Then I want to display a table showing the opportunities each rep has closed in the pay period.  I chose to use apex:repeat to iterate through the list of sales reps.  In each iteration, I passed the apex:repeat var to a method to query for opportunities owned by that rep.  The problem I'm encountering is that when the var is passed into the method, the method does not see the var value, it shows up as blank.  Why is this, and is there a workaround?

 

I also realized that running a new opportunity query for each sales rep is inefficient, so another approach would be to run one query at the start for all opportunities, then in the method just filter the list of opps down to those that are applicable to each rep.  I tried this as well, but ran into the same problem - the var value will not pass into the method, so I have no way to use it to filter the list of opps to just that rep.

 

Note that due to the team/pod structure, some reps will get paid partial commissions on opportunities owned by other reps.  I was going to add extra logic for this once I got the basic page working.  This complexity prevents me from doing a simple single list/query and just grouping the opps by the owner - this will not work with the extra complexity needed.

 

What am I missing here?  Can anyone offer a suggestion for how to fix this or to take a different approach?  Here is my code:

 

<apex:page controller="CommissionCalc">
<br></br>  
    <apex:pageBlock title="Commissions">

        <apex:form >
        <apex:actionFunction name="updateResults" action="{!updateResults}" rerender="Results"/>
        <apex:outputLabel value="Pay Date: " /> 
        <apex:selectlist value="{!dateRange}" multiselect="false" size="1" onChange="updateResults();">
            <apex:selectOption itemValue="" itemLabel="Select Date"/>
            <apex:selectOption itemValue="2012-01-16" itemLabel="Jan 16 2012"/>
            <apex:selectOption itemValue="2012-01-31" itemLabel="Jan 31 2012"/>
            <apex:selectOption itemValue="2012-02-15" itemLabel="Feb 15 2012"/>
            <apex:selectOption itemValue="2012-02-28" itemLabel="Feb 28 2012"/>
        </apex:selectlist>      
        </apex:form>
        
        <apex:outputPanel id="Results">

        <apex:repeat value="{!repNames}" var="repName"/>
            <br/><apex:outputText value="{!repName}"/><br/>

        <apex:pageBlockTable value="{!opps}" var="o">
            <apex:column value="{!o.Name}"/>
            <apex:column value="{!o.OwnerId}"/>
            <apex:column value="{!o.CloseDate}"/>
            <apex:column headerValue="Opportunity Amount" value="{!o.Amount}"/>               
        </apex:pageBlockTable>
        </apex:repeat>
        </apex:outputPanel>

    </apex:pageBlock>
</apex:page>

 

Controller:

 

public class CommissionCalc {
    List<Opportunity> opps;
    public String dateRange;
    public String repName;
    List<String> repNames = new String[] {'00570000001b7UQ','00570000001ZelI','00570000001a42K'};

    
    public List<Opportunity> getOpps(){
        if(dateRange == null ) { return null; } else {     
        opps = [select Id, Name, Amount, CloseDate, OwnerId, Pay_Period__c from Opportunity where OwnerId = :repName and StageName = 'Closed Won' and Pay_Period__c = :dateRange];

// QUERY ABOVE IS WHAT DOES NOT WORK - REPNAME VAR COMES IN AS NULL, EVEN THOUGH IT HAS A VALUE IN THE PAGE ITSELF

return opps; } } public List<String> getRepNames() { return repNames; } public String getDateRange() { return dateRange; } public void setDateRange(String s) { dateRange = s; } public Pagereference updateResults() { getOpps();
return opps; } }

 

 

 

 

 

 

 

aballardaballard

The repeat variable is NOT passed to the controller.   It is for reference in the page markup within the repeat.    And in general, you cannot count on the {!opps} expression being reexecuted each time through the repeat, since it is a constant expressin. 

 

You need to create a structure containing the data you want to iterate over.   In this case a list of objects where each object contains a name and a list of opportunities. 

 

mattomatto

Thank you for your reply and for the clarification, I really appreciate it.  I can create the data structure that you suggested and not rely on multiple queries or the expression being reexecuted, that makes sense.  I think I still have a problem with how to handle the iteration through the structure, however.  Ideally I would use a nested apex:repeat, with the first repeat iterating through the list of sales rep names, and then the second nested repeat iterating through the opportunities that each name should receive commissions for.

 

The problem is to make this truly dynamic, I would need the second nested repeat to be able to know which name the first repeat is on each time.  How do I accomplish this if the repeat variable is not passed to the controller?

 

Eugene PozniakEugene Pozniak

If I understand right, you want to group Opportunities with StageName = 'Closed Won' by OwnerId.

 

Try following:

 

Fill Map<String, List<Opportunity>> in your controller, e.g.:

List<String> repNames = new List<String> { /*Your values*/ };
Map<String, List<Opportunity>> ownerToOpportunities = Map<String, List<Opportunity>>();

for(Opportunity opp : [SELECT Name /*Add your fields*/ FROM Opportunity WHERE OwnerId IN :repNames AND StageName = 'Closed Won' /*Add additional where*/]) {
	if(ownerToOpportunities.containsKey(opp.ownerId)) {
		List<Opportunity> opportunities = ownerToOpportunities.get(opp.ownerId);
		opportunities.add(opp);
		ownerToOpportunities.put(opp.ownerId, opportunities);
	} else {
		ownerToOpportunities.put(opp.ownerId, new List<Opportunity> { opp } );
	}
}

 

On your page:

<apex:page>
	. . . 
	<apex:repeat value="{!ownerToOpportunities}" var="owner">
		<apex:pageBlockSection title="owner">
			<apex:pageBlockTable value="{!ownerToOpportunities[owner]}" var="opportunity">
				. . .
				<apex:column value="{!opportunity.Name}" />
				<!-- Add columns which you need -->
				. . .
			</apex:pageBlockTable>
		</apex:pageBlockSection>
	</apex:repeat>
	. . .
</apex:page>

 

Hope, it will be usefull for you.