+ Start a Discussion
Chad HammondChad Hammond 

Deeper understanding of Lightning Components and/or JavaScript

I realize this is a relativly new thing but I am new to the salesforce platform in general and not sure if my questions are lightning component specific, or more a general salesforce question, so here goes.
I am working through the workbook: http://www.salesforce.com/us/developer/docs/lightning/lightning.pdf and ran into a couple things I just can't make sense of.

1. Prefix's.
    a. I know in visualforce the "c:" prefix means you're using a component. I posted the code below as a reference. In the formhelper.js line "  var action = component.get("c.getExpenses");" what is the "c." referencing?
   b. in the line "action.setCallback(this, function(a){" what is the "a"? is it related to the "A" in "$A.enqueueAction(action);"?
   c. What is the "v" prefix referencing in "var expenses = component.get( "v.expenses");"?

My best guess is that "v"  is for accessing a variable, and "c" for a component, while the "a" passed into the function is a generic placeholder for something (but Idk what...). I don't see anywhere in the code where these 3 prefixes are initialed or declared, which is throwing me off. I'm a Java guy and learning javascript as well as salesforce, so i'm sure it's something obvious that I just don't know yet. I just want to thouroughly understand the example and this piece is giving me grief.


FormHelper.js:
({
    getExpenses : function(component) {
        var action = component.get("c.getExpenses");
        var self = this;
        action.setCallback(this, function(a){
            component.set("v.expenses", a.getReturnValue());
            self.updateTotal(component);
        });
        $A.enqueueAction(action);
    },
    updateTotal : function(component){
        var expenses = component.get( "v.expenses");
        var total = 0;
        for(var i=0; i<expenses.length; i++){
            var e = expenses[i];
            total += e.zoidberg__Amount__c;
        }
        //Update counters
        component.set("v.total",total);
        component.set("v.exp" ,expenses.length);
    },
    createExpense : function(component, expense){
        
        this.upsertExpense(component, expense, function(a) {
            
            var expenses = component.get("v.expenses");
            expenses.push(a.getReturnValue());
            component.set("v.expenses",expenses);
            this.updateTotal(component);
            
        });
    },
    upsertExpense : function(component, expense, callback){
        var action = component.get("c.saveExpense");
        action.setParams({
            "expense":expense
        });
        if(callback){
            action.setCallback(this,callback);
        }
        $A.enqueueAction(action);
    }
})

formController.js:
({
    doInit : function(component, event, helper) {
        helper.getExpenses(component);
    },
    createExpense : function (component,event,helper){
        var amtField = component.find("amount");
        var amt = amtField.get("v.value");
        if(isNaN(amt)||amt==''){
            amtField.setValid("v.value",false);
            amtField.addErrors("v.value",[{message:"Enter an expense amount."}]);
        }
        else{
            amtField.setValid("v.value",true);
            var newExpense = component.get("v.newExpense");
            helper.createExpense(component,newExpense);
        }
    },
    updateEvent : function(component, event, helper){
        helper.upsertExpense(component,event.getParam("expense"));
    },
    waiting : function(component, event, helper){
        component.set("v.wait","updating...");
    },
     doneWaiting : function(component, event, helper){
        component.set("v.wait","");
    },
})

form.cmp:
<aura:component controller="zoidberg.ExpenseController">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:handler event="zoidberg:updateExpenseItem" action="{!c.updateEvent}"/>
    <aura:handler event="aura:waiting" action="{!c.waiting}"/>
    <aura:handler event="aura:doneWaiting" action="{!c.doneWaiting}"/>
    <aura:attribute name="wait" type="String"/>
    <aura:attribute name="expenses" type="zoidberg.Expense__c[]"/>
    <aura:attribute name="newExpense"
                    type="zoidberg.Expense__c"
                    default="{ 'sobjectType': 'zoidberg__Expense__c',
                                 'Name': '',
                                 'zoidberg__Amount__c': 0,
                                 'zoidberg__Client__c': '',
                                 'zoidberg__Date__c': '',
                                 'zoidberg__Reimbursed__c': false
                             }"/>
    
    <!-- Attributes for Expense Counters -->
    <aura:attribute name= "total" type="Double" default="0.00"/>
    <aura:attribute name="exp" type="Double" default="0" />
    <div class="wait">
        {!v.wait}
    </div>
    <!-- Input from using components -->
    <form>
        <fieldset>
            <ui:inputText aura:id="expname" label="Expense Name"
                          class="form-control"
                          value="{!v.newExpense.name}"
                          placeholder="My Expense" required="true"/>
            <ui:inputNumber aura:id="amount" label="Amount"
                          class="form-control"
                          value="{!v.newExpense.zoidberg__Amount__c}"
                          placeholder="20.80" required="true"/>
            <ui:inputText aura:id="client" label="Client"
                          class="form-control"
                          value="{!v.newExpense.zoidberg__Client__c}"
                          placeholder="ABC Co."/>
            <ui:inputDateTime aura:id="expdate" label="Expense Date"
                          class="form-control"
                          value="{!v.newExpense.zoidberg__Date__c}"
                          displayDatePicker="true"/>
            <ui:inputCheckbox aura:id="reimbursed" label="Reimbursed?"
                          class="form-control"
                          value="{!v.newExpense.zoidberg__Reimbursed__c}"/>
            <ui:button label="Submit" press="{!c.createExpense}"/>
        </fieldset>
    </form>
    
    <!--Expense Counters -->
    <div class="row">
        <!--Change the counter color to red if total amount is more than 100 -->
        <div class= "{!v.total >= 100 ? 'alert alert-danger' : 'alert alert-success'}">
            <h3>Total Expenses</h3>$
            <ui:outputNumber value="{!v.total}" format=".00" />
        </div>
        <div class="alert alert-success">
            <h3>No. of Expenses </h3>
            <ui:outputNumber value="{!v.exp}"/>
        </div>
    </div>
    <!--Display expense records -->
    <div class="row">
        <aura:iteration items="{!v.expenses}" var="expense">
           <zoidberg:expenseList expense="{!expense}"/>
        </aura:iteration>
    </div>
</aura:component>
Best Answer chosen by Chad Hammond
SkipSaulsSkipSauls
Hi Chad,

Here are a few answers to hopefully clear things up:

c is for controller, including the client-side JavaScript, e.g., formController.js and server-side Apex, e.g., OpportunityController.apxc. It is often referenced as "{!c.doSomething}"  in an expression in the markup, or as component.get("c.getSomething") from JavaScript. Note that the client- and server-side controllers are indistinguishable when called from JavaScript, so you need to use a naming convention to ensure that the expected function is called. I would suggest "do", "handle", and similar for the client-side controller, as this is where events are handled, and "get", "list", etc. for the server-side, as this is where data is accessed.

a is the action in this case, but this is just a variable name and can be anything you wish. The "action" and "a" variables are equivalent in this case. The most common use of the "a" in the callback is to get the value from the action, as in a.getReturnValue(). This will be the value that was returned from the server-side Apex controller, typically a JavaScript object that maps to the Apex object.

v is the view, and like c this is part of the framework and not just a convention. The most common use of "v" is to access the attributes on the component, as in expressions with "{!v.someAttribute}" or in JavaScript with component.get("v.someAttribute") and the like.

Let me know if this doesn't help and I'll provide more details and/or examples.

All Answers

SkipSaulsSkipSauls
Hi Chad,

Here are a few answers to hopefully clear things up:

c is for controller, including the client-side JavaScript, e.g., formController.js and server-side Apex, e.g., OpportunityController.apxc. It is often referenced as "{!c.doSomething}"  in an expression in the markup, or as component.get("c.getSomething") from JavaScript. Note that the client- and server-side controllers are indistinguishable when called from JavaScript, so you need to use a naming convention to ensure that the expected function is called. I would suggest "do", "handle", and similar for the client-side controller, as this is where events are handled, and "get", "list", etc. for the server-side, as this is where data is accessed.

a is the action in this case, but this is just a variable name and can be anything you wish. The "action" and "a" variables are equivalent in this case. The most common use of the "a" in the callback is to get the value from the action, as in a.getReturnValue(). This will be the value that was returned from the server-side Apex controller, typically a JavaScript object that maps to the Apex object.

v is the view, and like c this is part of the framework and not just a convention. The most common use of "v" is to access the attributes on the component, as in expressions with "{!v.someAttribute}" or in JavaScript with component.get("v.someAttribute") and the like.

Let me know if this doesn't help and I'll provide more details and/or examples.
This was selected as the best answer
Ken KoellnerKen Koellner
Something that I suspect is that "v." and "c." are well-known references for view and controller and so you have to use "v." and "c.".

But "a" I believe that is code-definied. It's just a parameter declaration for an anonymous function.
The code --
this.upsertExpense(component, expense, function(a) {
            
            var expenses = component.get("v.expenses");
            expenses.push(a.getReturnValue());
            component.set("v.expenses",expenses);
            this.updateTotal(component);
            
        });
Coudl just as easily be --
this.upsertExpense(component, expense, function(myActionParm) {
            
            var expenses = component.get("v.expenses");
            expenses.push(myActionParm.getReturnValue());
            component.set("v.expenses",expenses);
            this.updateTotal(component);
            
        });



 
oski93oski93
@SkipSauls - what does 'e' represent? Event?
Willi WerkelWilli Werkel
What I found really confusing is that c also stands for the default namespace in orgs without their own namespace.
As I defined a namespace for my dev org, I found myself having to replace some of the c by my namespaces name but leave others untouched. Took me a few tries to get the Expenses example running but I am still not convinced that I know which c stands for what.
michael.demegliomichael.demeglio
I'm getting an Internal error when running Step 5 of the expenseTracker sample app. Judging by the debug logs, the upsert call isn't getting through from javascript to my AuraEnabled controller method. No DML is happening and the callback isn't firing. Anyone else have this problem? 
Amritesh_SinghAmritesh_Singh
Hi @michael.demeglio

Did you got your answer .? I am also facing the same issue with expenseTracker sample app.

upsertExpense : function(component, expense, callback) {
        var action = component.get("c.saveExpense");
        action.setParams({
            "expense": expense
        });
        if (callback) {
            action.setCallback(this, callback);
        }
        $A.enqueueAction(action);
    }


There is some issue with action.setParams here. If I debug expense parameter ,all the values are passing correctly,but the callback response state is coming as Error and I am getting below popup error message:

Something has gone wrong. Error in $A.getCallback() [TypeError: Cannot read property 'Amount__c' of null]
Failing descriptor: {markup://amsf:form}.
Please try again.


Please let me know if anyone has any solution for this.

Thanks,
Amritesh
arpit sethi 23arpit sethi 23
Hello Amritesh_Singh,

Can you please paste your whole code?