đź“Ł Attention Salesforce Certified Trailblazers! Link your Trailhead and Webassessor accounts and maintain your credentials by December 14th. Learn more.
close
trailhead

Learn Coding Concepts

Learning Objectives

After completing this unit, you’ll be able to:
  • Map fundamental concepts, such as controllers and requests, from Visualforce to Lightning components.
  • Avoid the #1 syntax error in Lightning components code.
  • Describe the advantage of loosely coupled components, and how loose coupling is accomplished.

Concept: Controllers

At last! A concept with a name you recognize!

Chute! Despite the familiar name, this is an area where your Visualforce expertise doesn’t apply to Lightning components. One of the staple features of Visualforce is the Standard Controller. By setting a single attribute for a page, you can bind that page to an sObject type, and get a slew of automatic behavior—reading and writing record data, for example—without writing any code. With the Standard Controller, many non-programmers can create totally custom Visualforce pages. There’s nothing like this for Lightning components. Creating a component that works with records requires writing code.

How about Visualforce custom controllers? They involve writing your own code. How different can they be from Lightning component controllers? Chute!

First, remember that Visualforce controllers run on the server side, while Lightning component controllers run on the client side. And sometimes on the server side, too. Visualforce controllers are written in Apex, while Lightning component controllers are written in JavaScript. And sometimes also in Apex.

Visualforce Controller Architecture Lightning Components Controller Architecture
Visualforce controller architecture Lightning components controller architecture

As you can see in the illustration, the two are different architecturally. This difference, the client-side controller, affects the code you write. Your Lightning component controller code runs on the client, while the data is stored on the server. In the absence of caching, every time you want new data you make a server request of some sort. That’s code you maybe weren’t writing for your Visualforce controllers. Further, remote requests are written in an asynchronous, callback-based style, which might be very different from your existing controller code.

Also, many custom Visualforce controllers and extensions use the StandardController or StandardSetController Apex classes, to extend built-in behavior rather than replacing it. These are, alas, tightly bound to Visualforce. You can’t reuse them in your Lightning components server-side controller code. More code you’ll need to write yourself.

Ladder! Here’s some good news. If you create your Visualforce pages using JavaScript remoting and Apex @RemoteAction methods, you already design your controller code in a way that can be highly reusable for Lightning components. You need to update existing code, but you’ve already made the jump to the new architecture.

Ladder! Finally, let’s end on the really good news. Lightning Data Service (LDS) is only available with Lightning components. It’s the closest thing Lightning components has to a standard controller. It does require writing some code. Not as much as a plain controller, but some. But LDS is far more powerful, and includes built-in caching, update notification, and other crazy cool features. Once you make the switch, you won’t want to go back. See the Resources section to learn more about LDS.

Concept: Actions

In Visualforce, an action is a controller method that returns a PageReference at the end of it. Usually attached to a button or a link, an action represents work the user wants the app to do, followed by navigating to a next or results page, or maybe just back “home.” For example, an edit button calls an action method that loads data for a record, and then navigates to a page with an edit form.

Ladder! Lightning component actions are similar. Actions are functions you write in JavaScript and attach to user interface elements. Ladder time at last!

But wait. There are important differences, and if you miss them you’ll be chuting down instead of laddering up.

First, realize that actions aren’t direct method or function calls, in either Visualforce or Lightning components. You don’t call them, the framework invokes them when appropriate. So far the same.

However, in Visualforce your actions are methods defined on an Apex class. You get some language infrastructure around your method, like instance variables, and class and instance methods.

Chute! Lightning component actions aren’t defined on a class. Instead, they are function definitions declared on the value (right hand) side of elements in a JavaScript object in object-literal notation containing name-value pairs. Here’s a trivial example:
({
    myAction : function(component, event, helper) {
        // add code for the action
    },
})

This difference in declaration style has syntactic and structural consequences. On the syntax side, notice that comma after the function declaration (on line 4). Separate action handlers with commas!In Apex that would be a syntax error. In object-literal notation, a missing comma between two action definitions is the syntax error. Be aware that a missing comma can be a tough error to spot, so get in the habit of always separating your action handlers with commas.

Tip

Tip

If you’re using the Force.com IDE, or another tool that allows plug-ins, consider adding a JavaScript validation tool, such as ESLint, to your environment. Since this is a JavaScript syntax error, pretty much any lint-style tool will catch this before you’ve gotten more than two lines away from the error.

The structural differences prevent controller code from accessing other functions or values inside the controller resource. You can’t declare helper methods in the controller, you can’t create instance or static properties, and so on. Instead, put reusable code into an associated helper, and store instance values as attributes on your component. Let’s look at that last bit in detail.

Concept: Properties vs. Attributes vs. “Expandos”

Apex properties are (effectively) instance variables with custom logic behind them. When you define them in a Visualforce controller or extension, expressions on a page can use them. While getting and setting a controller property isn’t supposed to have side effects (the computer science term is idempotent), properties can call helper methods to share or abstract the logic behind them. Properties are really useful—and common—in Visualforce controllers.

While you might want to create similar properties in your Lightning component JavaScript controller file, you can’t. You can try to add them to the helper, which might appear to work. However, the helper is a singleton, shared across all instances of your component. It’s more like a class static variable, so you can’t use it to save the state of an individual component.

So, what do you do?

Component Attributes

If you need to access the value in an expression in your component markup, use a component attribute. A component attribute is declared like this.
<aura:attribute name="myAttribute" type="Integer"/>
Component attributes require, at a minimum, a name and a data type. (There are optional attributes for defaults and so on.) Reference the attribute in markup using standard expression syntax.
{!v.myAttribute}
(We’ll have more to say about expressions and expression syntax in the next module.)

Get and set the attribute value in your controller JavaScript code using (surprise!) the get and set methods.Use get and set functions to get and set component attribute values

The get and set methods are functions available on the component parameter passed into the myAction action handler function.
({
    myAction : function(component, event, helper) {
        var counter = component.get("v.myAttribute");
        counter++;
        component.set("v.myAttribute", counter);
    },
})
Here get (line 3) retrieves the value of the myAttribute component attribute and assigns the value to the local counter variable. counter gets incremented, and then set (line 5) updates the component attribute.

If other components shouldn’t fiddle with the value of your component’s attribute, make the attribute private. Otherwise, the attribute becomes part of your component’s public API.

JavaScript Expandos and Private Attributes

Attributes, with their get/set dance, sometimes feel “high ceremony” to Visualforce developers. If you’re JavaScript-savvy, you might try to use a quirk of JavaScript, and set a value on the component instance from within an action function.

component._myExpando = "A new string variable";

This expando, created on the fly, becomes part of your component instance. It looks like a nice, lightweight private instance variable.

The problem is that expandos create an opportunity for subtle bugs and memory leaks. While they’ll work, they’re also likely to cause problems, and for that reason we recommend against them. The recommended approach is to create a component attribute, and set its access level to private. (We also recommend prefixing the names of private attributes with an underscore (for example, _myAttribute), to make it obvious that they’re private variables.)

Concept: Method Calls vs. Events

Let’s finish this module with one last Big Concept.

Your Visualforce pages (probably) run on methods. Expressions, properties, and actions all boil down to function calls. Function (or method) calls are easy to see—you declare them in your controller Apex class. It’s easy to follow the order of execution and reason about behavior. (Yes, “easy” is a relative term. Work with me.)

Method calls also represent tight coupling between the parts of your app. Your page is tightly coupled with its controller and extensions, which in turn might be coupled with other Apex classes. The relationships between pieces, though easy to follow, are also potentially fragile or hard to reuse.

The Lightning Component framework was designed to address many of these limitations of Visualforce. In particular, components are (intended to be) loosely coupled. The mechanism for this loose coupling is events.

You can think of a method call as a “hard line” connecting the caller with the callee, like a physical wire. Flip a switch at one end, a light comes on at the other. With physical wiring, you can have multiple devices on the same circuit—but when you want the light on in the hall, you also get the light in the closet. And so it is with software: The more you reuse tightly coupled parts of a system, the more you have side effects, and the harder it is to splice in new pieces.

Using events to communicate between Lightning components creates “wireless” connections. Flipping a switch (firing an event) is like a radio signal. If there’s someone (another component) out there listening on that frequency (has a handler for that event), it can take action when it receives the signal. But you, the lonely wireless operator, don’t know if anyone out there is listening. Likewise, you write your component so that it behaves correctly, whether its event is received and handled or not.

Our metaphor is getting strained, so let’s conclude with two specific bits of advice.

  • Give the principles of composition and loose coupling a fair shake and some time, and you’ll grow as a developer. The approach is different than what you’re used to with Visualforce. Some would say it’s harder, but we think it’s a matter of learning and experience. Lightning components isn’t the only framework built on these principles!
  • Don’t treat methods the same as you would in Visualforce. You’ll inevitably discover that you can publish and call methods in your Lightning components. It’s tempting, when you run into a design challenge, to fall back on what you know. Resist temptation. Lightning component methods do have their appropriate uses. Use them when they’re the right tool for the job. Just don’t make them the proverbial hammer that you solve every problem with.
retargeting