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
etessetess 

Passing Variables Into Apex Methods

I am new to Apex and not quite sure the syntax for passing a variable into one of my methods from a Visualforce page. I have an apex:repeat loop on my VF page that I'd like to perform a call to one of my apex methods within.

 

The VF page loop looks like this:

 

<apex:repeat value="{!ListCategories}" var="this">
   {!this.name} - SUBTOTAL HERE <br/>
</apex:repeat>

 

 The method looks like this:

 

 

 

Public Decimal calcSubtotal(String Category) {
     Decimal count = 0;

     for (QuoteLineItem a : [select category__c, UnitPrice from QuoteLineItem where category__c = :Category AND Quote.Opportunity.Id = :qte.Opportunity.Id]) {       
          count += a.UnitPrice;
     }
        
     return count;
}

 

What I want to do is replace where it says "SUBTOTAL HERE" on my VF page with the subtotal for that particular category. What I can't seem to figure out is how do I pass the "this.name" variable from my VF loop into my calcSubtotal method? The Standard controller is Quote and this method is a controller extension.

 

Best Answer chosen by Admin (Salesforce Developers) 
SteveBowerSteveBower

Where is ":qte" being defined?  (Assuming it's defined elsewhere in the controller...)

 

Also, if cx is a List, then you need to "add()" to it, not just say cx.category =...

 

 

So, to clean it up...

    public class catSubtotal {
        public String category {get; set;}
        public Decimal subtotal {get; set;}

        catSubtotal(AggregateResult ar) {
           this.category = ar.get('category__c');
           this.subtotal = ar.get('expr0');
        }
    }

    
    Public List<catSubtotal> getAllSubtotals() {
    
        List<catSubtotal> cx = new List<catSubtotal>();
        
        for (AggregateResult in [SELECT category__c, SUM(TotalPrice) FROM QuoteLineItem WHERE Quote.Opportunity.Id = :qte.Opportunity.Id GROUP BY ROLLUP(category__c)]
         ) cx.add(new catSubTotal(ar));

        return cx;
        
    }

 

 

Also, if getAllSubtotals might be called again and again without changing the qte value, then you might want to put the

definition of cx outsite the get method, set it on the first call to the get, and on subsequent calls check to see if it's empty and if not, return the current values.  After all, there's no reason to do the query again and again with the same qte value.

 

  if (!cx.isEmpty) return cx;

 

If you need to change the qte number, then in the setter for qte you could call clearSubtotals(), which would do nothing but:  cx.clear();

 

Best, Steve.

 

 

All Answers

sinsiterrulezsinsiterrulez

Use apex:param to pass variable into controller and then use it to access it in your method.

etessetess

Thanks. I've been pursuing that, but I can't seem to get a simple test of passing a param into my function and returning it back to work-

 

 

// VF PAGE CODE

<apex:outputText value="{!theCategory}">
    // this.id works fine; displays the correct id when just displayed
<apex:param name="theCategory" value="{!this.id}" /> </apex:outputText> // CONTROLLER CODE Public String getTheSpot() { String theCategory = ApexPages.currentPage().getParameters().get('theCategory'); return theCategory; }

I'm just getting nothing back

 

 

WizradWizrad

Params generally require an action, such as a button click.

 

E.g. you click a button, it fires a method in your controller, and when you click the button the param is placed up in the url and you can pull it down when the method is executing.

 

For your use case, I would suggest an aggregate query.  You want to SUM the Unit Price field and group by the category field.

 

Then in your VF your repeat tag can iterate over the aggregate results returned from the aggregate query.

 

etessetess

Ah - that is definitely what I was looking for. Are there any examples of how to use apex:repeat to display an Aggregrate Result? I can't seem to find any, and it's giving me errors as I don't know how to refer to the fields.. it seems different then a regular query..

WizradWizrad

Well I probably spoke a tiny bit too soon.

 

Keep the aggregate query (info can be found here).

 

Then in your apex class create an innerclass e.g.

 

 

public class MyCoupler {
  public String category {get; set;}
  public Double subtotal {get; set;}
}

 Now iterate over your aggregate results, instantiating a list of MyCoupler objects, then in your VF iterate over your list of MyCoupler objects.

 

Can't use an aggregate result with repeat tag because you need to be able to pass parameters to your aggregate result's get method to get values out of it, e.g.

 

 

aggregateResult.get('myValue');

 

Which cannot be done within VF.

 

 

etessetess

I understand the concept, having trouble with the syntax. I apologize for all the questions - I'm new to Apex. I've put in the following code but I'm getting an error.

 

Compile Error: Initial term of field expression must be a concrete SObject: LIST<quoteExtension.catSubtotal> 

 

 

    public class catSubtotal {
        public String category {get; set;}
        public Decimal subtotal {get; set;}
    }
    
    Public List<catSubtotal> getAllSubtotals() {
    
        AggregateResult[] groupedResults = [SELECT category__c, SUM(TotalPrice) FROM QuoteLineItem WHERE Quote.Opportunity.Id = :qte.Opportunity.Id GROUP BY ROLLUP(category__c)];
        
        List<catSubtotal> cx = new List<catSubtotal>();
        
        for (AggregateResult ar : groupedResults) {
            cx.category = ar.get('category__c');
            cx.subtotal = ar.get('expr0');
        }
        
        return cx;
        
    }

 

 

SteveBowerSteveBower

Where is ":qte" being defined?  (Assuming it's defined elsewhere in the controller...)

 

Also, if cx is a List, then you need to "add()" to it, not just say cx.category =...

 

 

So, to clean it up...

    public class catSubtotal {
        public String category {get; set;}
        public Decimal subtotal {get; set;}

        catSubtotal(AggregateResult ar) {
           this.category = ar.get('category__c');
           this.subtotal = ar.get('expr0');
        }
    }

    
    Public List<catSubtotal> getAllSubtotals() {
    
        List<catSubtotal> cx = new List<catSubtotal>();
        
        for (AggregateResult in [SELECT category__c, SUM(TotalPrice) FROM QuoteLineItem WHERE Quote.Opportunity.Id = :qte.Opportunity.Id GROUP BY ROLLUP(category__c)]
         ) cx.add(new catSubTotal(ar));

        return cx;
        
    }

 

 

Also, if getAllSubtotals might be called again and again without changing the qte value, then you might want to put the

definition of cx outsite the get method, set it on the first call to the get, and on subsequent calls check to see if it's empty and if not, return the current values.  After all, there's no reason to do the query again and again with the same qte value.

 

  if (!cx.isEmpty) return cx;

 

If you need to change the qte number, then in the setter for qte you could call clearSubtotals(), which would do nothing but:  cx.clear();

 

Best, Steve.

 

 

This was selected as the best answer
SteveBowerSteveBower

Oh... one more thought... why are you bothering with the whole catSubtotal class in the first place.  why not have getAllSubtotals just return a List<AggregateResult> and use that directly in your vf?   Best, Steve.

SteveBowerSteveBower

Oh... I see the previous discussion.... Wizard is right that you couldn't use the Repeat to iterate over a *single* Aggregate Result object, but you're retrieving a list of them aren't you?  And you can iterate over that and then use <apex:outputFields> directly on the Category and Expr0 fields...    Unless I'm missing something.   Best, Steve.  (who is done now.)

Pradeep_NavatarPradeep_Navatar

In your code the data ({!ListCategories} list type) is already coming from controller to bind with repea. So I think you need not to pass this again into the controller. You have already "this.name" in your controller.

 

Find below a sample VF code :

 

            ---------------- VF Page ---------------

            <apex:page>

                        <apex:form>

                                                Enter your name : <apex:inputText value="{!propName}" />

                                    <apex:commandButton value="Submit" action="{!SubmitData}" />

                        </apex:form>

            </apex:page>

 

 

            ------------- Controller code -----------

            public class Organization_Registration_Controller

            { 

                        public String  propOrgName{ get; set; }

                        public void SubmitData()

                        {

                                    Account acc = new Account(name=propOrgName);

                                    Insert acc;

                        }

            }

etessetess

Basically at this point the issue seems to be getting the AggregateResult[] into a list I get repeat on...I am getting an error trying to assign the results to my catSubtotal class.

 

this.category = ar.get('category__c');

Compile Error: Illegal assignment from Object to String

 

etessetess

Ah.. needs to be this.category = (String) ar.get('category__c');

 

Alright, we'll see if this works! ;)