Learn Coding Concepts
Learning Objectives
- Map fundamental concepts, such as controllers and requests, from Visualforce to Aura components.
- Avoid the #1 syntax error in Aura 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!
Despite the familiar name, this is an area where your Visualforce expertise doesn’t apply to Aura 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 Aura 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 Aura component controllers?
First, remember that Visualforce controllers run on the server side, while Aura component controllers run on the client side. And sometimes on the server side, too. Visualforce controllers are written in Apex, while Aura component controllers are written in JavaScript. And sometimes also in Apex.
Visualforce Controller Architecture | Aura 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 Aura 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 Aura components server-side controller code. More code you’ll need to write yourself.
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 Aura components. You need to update existing
code, but you’ve already made the jump to the new architecture.
Finally, let’s end on the really good news. Lightning Data Service (LDS) is only available with Aura components. It’s the closest thing Aura 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.
Aura 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 Aura 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.

({ 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). 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.
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 Aura 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
<aura:attribute name="myAttribute" type="Integer"/>
{!v.myAttribute}
Get and set the attribute value in your controller JavaScript code using (surprise!) the get and set methods.
({ myAction : function(component, event, helper) { var counter = component.get("v.myAttribute"); counter++; component.set("v.myAttribute", counter); }, })
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.
Aura components were 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 Aura 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.
- Don’t treat methods the same as you would in Visualforce. You’ll inevitably discover that you can publish and call methods in your Aura components. It’s tempting, when you run into a design challenge, to fall back on what you know. Resist temptation. Aura 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.