Salesforce1 Lightning Components – Working with Controllers

The Lightning Component framework allows developers to define client-side controllers with methods that respond to client and server-side events. Learn how different controller types works together in a component.

Guest post: Peter Knolle is a Solutions Architect at Trifecta Technologies, Force.com MVP, and Salesforce Developer Group Organizer.  He holds six Salesforce certifications, blogs regularly at peterknolle.com, and is active on Twitter @PeterKnolle.

Salesforce1 Lightning Components includes a framework (the Lightning Component Framework) that allows developers to define client-side controllers with methods that respond to events such as user interactions or lifecycle events and server-side controllers with actions that run on the server and perform processing such as database interactions.  This post describes each type of controller and how they work together in a component.

Client-side (JavaScript) Controllers for Lightning Components

The client-side controllers are written in JavaScript and are automatically placed in a file in the component bundle named <component-name>Controller.js. Let’s look at a component and its controller that allows a user to update a Contact.

The component markup:

<aura:component controller="ContactController" > 
    <aura:attribute name="contactId" type="Id" required="true" />
    <aura:attribute name="contact" type="Contact"/>

    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <h2>{!v.contact.Name}</h2>
    <ul>
        <li>Email: <ui:inputEmail value="{!v.contact.Email}"/></li>
        <li>Phone: <ui:inputphone value="{!v.contact.Phone}"/></li>
    </ul>
    <ui:button label="Update" press="{!c.updateContact}"/>
</aura:component>

The controller JavaScript:

({
    doInit : function(component, event, helper) {
        helper.loadContact(component);
    },
    updateContact : function(component, event, helper) {
        helper.updateContact(component);
    }
})

The first thing to notice in the controller is the structure of it. It probably isn’t in a format you’re used to seeing such as the format of JavaScript files that you include in a page via a script tag and which just contain collections of functions. The component’s controller JavaScript file uses object literal notation, with each function declared as a named property and each function separated by a comma.

The second thing that you might notice is that each function has three parameters: component, event, and helper. If you look at the markup in the component it doesn’t appear that there is any sort of reference to these parameters. So where do these parameters come from? The answer is that the framework takes care of injecting the arguments to the controller methods, making them available as the parameters. The component parameter refers to the component. The event is the event that caused the controller method to be invoked. The helper is the helper for the component that contains common JavaScript for the component.

The component refers to the controller methods in two places. One is in its event handler for the framework initiated init event with {!c.doInit}. The other is in the handler for the user initiated press event of the button with {!c.updateContact}. The “c” is what’s called a value provider and contains the actions and event handlers for the component (client-side and server-side). Another value provider that you’ll use a lot is the “v” value provider which contains the attribute set of the component. When the init event is handled or the button is pressed the controller functions are called by the framework with the injected arguments.

Server-side (Apex) Controllers for Lightning Components

Apex controllers define the server-side actions available to the component. The Apex controller is specified as an attribute on the aura:component. Apex controllers for Lightning Components contain static methods and are stateless. This is in contrast to Visualforce controllers which may have a view state. The Lightning Apex controllers are similar to Visualforce controllers that only contain @RemoteAction methods.

The Apex controller for the contact component has two methods defined that can be invoked from the component’s JavaScript.

public with sharing class ContactController {

    @AuraEnabled
    public static Contact getContact(Id contactId) {
        return [
            SELECT Id, Name, Email, Phone 
            FROM Contact
            WHERE Id =:contactId
        ][0];
    }

    @AuraEnabled
    public static Contact saveContact(Contact con) {
        update con;
        return con;
    }
}

Methods in the Apex controller that can be called must be static and annotated with @AuraEnabled. Additionally, any properties or accessor methods on the returned object must be @AuraEnabled. In this case they both return a Contact, which is, but if you are using a custom class or some built-in Apex classes (e.g., SelectOption) they may not be. In that case you can just create your own inner class and copy the values you need into @AuraEnabled properties on it.

Using Them Together

Apex controller actions are never referenced directly in markup, but instead are called from the JavaScript controller. More typically the controller delegates to the helper to call the server-side action, as the client-side contact controller delegates to its helper’s loadContact method.

loadContact : function(component) {
    var action = component.get("c.getContact");

    action.setParams({
        contactId : component.get("v.contactId")
    });

    action.setCallback(this, function(a) {
        if (a.getState() === "SUCCESS") {
            component.set("v.contact", a.getReturnValue());
        } else if (a.getState() === "ERROR") {
            $A.log("Errors", a.getError());
        }
    });

    $A.enqueueAction(action);
}

The loadContact method follows a fairly standard pattern for interacting with an Apex controller:

  1. Get the action
  2. Set its parameters
  3. Define the callback
  4. Enqueue the action

The action is enqueued and the framework takes care of calling it asynchronously and invoking its callback with the return value, when ready. The action is actually placed in a batch to reduce network traffic, but that is completely transparent to us.

The server-side action is also provided by the “c” value provider. This is the same value provider that provides the JavaScript controller event handler which handles the press event of the button and the init event. Because of this, you need to make sure that you do not name your Apex controller methods with the same name as your JavaScript controller methods. It’s easy to make the mistake of naming them same because it is natural to want to be consistent in naming. For example, I named the JavaScript controller method loadContact, but the Apex controller method getContact, instead of naming them both getContact or both loadContact.

The callback has the exact same action that is being called passed back into it to be used in getting information about the result of the action. In other words, it is true that action === a. The action object has useful methods to get the state, the return value, and any possible error messages. The getContact action’s callback updates the component’s contact attribute with the value returned from the Apex controller, which in turn will result in the component being rerendered with the new values.

More

For more information on controllers in the Lightning Component Framework, refer to the Lightning Component Developer’s Guide. For a quick overview and introduction to Lightning Components, visit the Lightning Components page on Salesforce Developers. If you’re ready to learn hands-on while earning badges to demonstrate your skills, start the Lightning Components module in Trailhead.

Leave your comments...

Salesforce1 Lightning Components – Working with Controllers