Newer Version Available

This content describes an older version of this product. View Latest

Step 3: Load the Expense Data

Load expense data using an Apex controller class. Display this data via component attributes and update the counters dynamically.
Create the expense controller class.
  1. Click File | New | Apex Class and enter ExpenseController in the New Class window. This creates a new Apex class, ExpenseController.apxc.
  2. Enter this code.
    1public with sharing class ExpenseController {
    2    @AuraEnabled
    3    public static List<Expense__c> getExpenses() {
    4
    5        // Perform isAccessible() check here
    6        return [SELECT Id, Name, Amount__c, Client__c, Date__c,
    7        Reimbursed__c, CreatedDate FROM Expense__c];
    8    }
    9}

    The getExpenses() method contains a SOQL query to return all expense records. Recall the syntax {!v.expenses} in form.cmp, which displays the result of the getExpenses() method in the component markup.

    For more information on using SOQL, see the Force.com SOQL and SOSL Reference.

    Note

    @AuraEnabled enables client- and server-side access to the controller method. Server-side controllers must be static and all instances of a given component share one static controller. They can return or take in any types, such as a List or Map.

    For more information on server-side controllers, see Apex Server-Side Controller Overview.

    Note

  3. In form.cmp, update the aura:component tag to include the controller attribute.
    1<aura:component controller="ExpenseController">

    If your org has a namespace, use controller="myNamespace.ExpenseController" instead.

    Note

  4. Add an init handler to load your data on component initialization.
    1<aura:component controller="ExpenseController">
    2  <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    3  <!-- Other aura:attribute tags here -->
    4  <!-- Other code here -->
    5</aura:component>
    On initialization, this event handler runs the doInit action that you’re creating next. This init event is fired before component rendering.
  5. Add the client-side controller action for the init handler. In the sidebar, click CONTROLLER to create a new resource, formController.js. Enter this code.
    1({
    2    doInit : function(component, event, helper) {
    3       //Update expense counters
    4       helper.getExpenses(component);
    5    },//Delimiter for future code
    6})
    During component initialization, the expense counters should reflect the latest sum and total number of expenses, which you’re adding next using a helper function, getExpenses(component).

    A client-side controller handles events within a component and can take in three parameters: the component to which the controller belongs, the event that the action is handling, and the helper if it’s used. A helper is a resource for storing code that you want to reuse in your component bundle, providing better code reusability and specialization. For more information about using client-side controllers and helpers, see Handling Events with Client-Side Controllers and Sharing JavaScript Code in a Component Bundle.

    Note

  6. Create the helper function to display the expense records and dynamically update the counters. Click HELPER to create a new resource, formHelper.js and enter this code.
    1({
    2  getExpenses: function(component) {
    3        var action = component.get("c.getExpenses");
    4        action.setCallback(this, function(response) {
    5            var state = response.getState();
    6            if (component.isValid() && state === "SUCCESS") {
    7                component.set("v.expenses", response.getReturnValue());
    8                this.updateTotal(component);
    9            }
    10        });
    11        $A.enqueueAction(action);
    12  },
    13  updateTotal : function(component) {  
    14      var expenses = component.get("v.expenses");
    15      var total = 0;
    16      for(var i=0; i<expenses.length; i++){
    17          var e = expenses[i];
    18
    19          //If you’re using a namespace, use e.myNamespace__Amount__c instead
    20          total += e.Amount__c;
    21      }
    22      //Update counters
    23      component.set("v.total", total);
    24      component.set("v.exp", expenses.length);
    25  },//Delimiter for future code
    26
    27})
    component.get("c.getExpenses") returns an instance of the server-side action. action.setCallback() passes in a function to be called after the server responds. In updateTotal, you are retrieving the expenses and summing up their amount values and length of expenses, setting those values on the total and exp attributes.

    $A.enqueueAction(action) adds the action to the queue. All the action calls are asynchronous and run in batches. For more information about server-side actions, see Calling a Server-Side Action.

    Note

  7. Save your changes and reload your browser.
    You should see the expense records created in Create an Expense Object. The counters aren’t working at this point as you’ll be adding the programmatic logic later.

Your app now retrieves the expense object and displays its records as a list, iterated over by aura:iteration. The counters now reflect the total sum and number of expenses.

In this step, you created an Apex controller class to load expense data. getExpenses() returns the list of expense records. By default, the framework doesn’t call any getters. To access a method, annotate the method with @AuraEnabled, which exposes the data in that method. Only methods that are annotated with @AuraEnabled in the controller class are accessible to the components.

Component markup that uses the ExpenseController class can display the expense name or id with the {!expense.name} or {!expense.id} expression, as shown in Step 2: Create A Component for User Input.

Beyond the Basics

Client-side controller definitions are surrounded by brackets and curly braces. The curly braces denotes a JSON object, and everything inside the object is a map of name-value pairs. For example, updateTotal is a name that corresponds to a client-side action, and the value is a function. The function is passed around in JavaScript like any other object.