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

Learn About Syntax and Code

Learning Objectives

After completing this unit, you’ll be able to:
  • Correctly implement controller action handlers and helper functions, and call helper functions from controller code.
  • Explain the difference between bound and unbound expressions.
  • Explain how Visualforce global variables and Lightning components global value providers are different.
  • Stretch goal: Explain the difference between “c.”, “c.”, and “c:”. (No, that's not a typo.)

Controller Syntax

We covered this conceptually in the Lightning Component Core Concepts module, but want to repeat some syntax details around client-side JavaScript controllers. This is an example controller.
({
    myAction : function(component, event, helper) {
        // add code for the action
    },

    anotherAction : function(component, event, helper) {
        // more code
    },
})
We want you to understand three specific things about the syntax here. All of these are different from what you’re used to with your Apex controllers.
  1. Chute! This isn’t a class. It’s a JSON object containing a map of name:value pairs. It can contain only action handlers, which you’ll never invoke directly.
  2. Your action handlers are declared as anonymous functions assigned to the action name (here, myAction and anotherAction). Your functions can accept up to three parameters, and only these parameters (component, event, and helper—though you can name them differently). The framework supplies them when it calls the handler.
  3. Most importantly, you separate your name:value pairs with a comma, highlighted in this graphic version of the same code. Tip: Add a comma after every action handler A quirk of JavaScript syntax means that the first comma in this example is mandatory, but the second one (which looks like a dangling mistake), is allowed but optional.

    Ladder! It’s a best practice to always add the optional comma after your last action handler, even though it’s not necessary, and might make some people’s OCD twitch. This is because at some later time you’ll probably add another action handler, and you’ll forget the comma. (Your humble author has done this too many times to admit publicly.) And then you’ll get a cryptic error, and spend time trying to figure it out. That’s a waste of time, and it’s totally avoidable.

Helper Syntax

Put functions that you want to reuse in the component’s helper. Helper functions also enable specialization of tasks, such as processing data and firing server-side actions. Call helper functions by referencing them through the helper parameter passed to your action function.
myAction : function(component, event, helper) {
    helper.aHelperFunction(component, 42);
},
Component helpers are declared with a similar syntax to controllers, as an object containing a map of name:value pairs. (And, you guessed it, they’re separated by commas just like the controller.)
({
    aHelperFunction : function(component, value) {
        // helper code here
    },
})
However, there are a few differences you need to know about.
  • Helper functions can be declared to take any parameters you want. You call the helpers, not the framework.
  • By convention, pass a reference to the component calling the helper as the first parameter to the helper.
  • Helpers are singletons, and are shared across all component instances. Don’t keep component state in a helper. Think of helpers more like static methods in your Apex controllers.
  • You can add non-functions to a helper, and have the values available to your controller action handlers—for example, an API credential you want to load only once. But keep in mind it’s a shared variable, and there’s nothing guarding against inappropriate access. Think—carefully—before you use this strategy.

Controllers vs. Helpers

So, what do you put in a controller action handler function, and what do you put in a helper?

Many people consider it a best practice to keep action handlers as simple and clear as possible, and abstract out the details into the helper. That’s a sensible approach, but there are others.

Our advice is to put code you want to reuse across action handlers into the helper. Beyond that, it’s a matter of taste and style, and your organization’s coding standards.

Expressions

Expression syntax in Visualforce and Lightning component markup is similar. Here’s an example.

The message: {! messageText }

Is this Visualforce or Lightning components markup? It’s Visualforce. The same markup throws an error if you use it in a Lightning component.*

How can you tell the difference? The expression references messageText, which is presumably a property or getter method on the page’s controller, or maybe on a controller extension. The value is coming “from somewhere” but there are a number of possibilities. You can’t really tell with Visualforce.

Lightning components don’t let you get away with pulling a value out of “somewhere.” Here’s the most likely corresponding Lightning component markup.

The message: {! v.messageText }

The key difference, the “v.”, is subtle when you’re first getting to know Lightning components. It’s the value provider for the view, which is the component itself, and it’s how you reference a component’s attributes. We tackle value providers in the next section. For the moment, just know that if you leave off the value provider, you get an error.

Chute! This is especially important to remember when you convert Visualforce markup to Lightning components. The markup looks similar, and it’s easy to copy-and-paste it into place. Don’t forget to add the value provider in every expression.

Two other points we want to make about Lightning components expressions and expression syntax. First, there are actually two different kinds of expressions in Lightning components: bound and unbound, which use different expression delimiters.

  • Bound expression: {! v.messageText }
  • Unbound expression: {# v.messageText }

The difference in syntax is one character, the exclamation point vs. the hash mark. The difference in behavior is either invisible, or profound, depending on context. The unbound version acts most like a Visualforce expression. Chute! The different syntax provides the similar behavior—intuitive, right?

Bound expressions add some Lightning components magic, creating a two-way binding between all uses of the value. If you change the value in one place, you change it everywhere. You can read up on the details in Data Binding Between Components.

Second, in the following example there are two expressions.
<aura:component ...>
    ...

    The message: {!v.message}

    <lightning:button label="Acknowledge"
        onclick="{!c.acknowledgeMessage}"/>

    ...
</aura:component>

The most obvious difference is the value provider, “v.” or “c.”. “v.” is the view, as we saw previously. “c.” is the controller. You use “c.” to reference actions in the controller. Here we bind an action to the button’s click event.

Although you can use a component attribute directly, as we do here with the {!v.message} string attribute, you reference functions in the controller. That is, you can’t call those functions directly. The result of evaluating the {!c.acknowledgeMessage} expression is a reference to a function, not a result value you can use directly. Adding the value provider doesn’t change that.

____________________

* There’s one exception, if messageText is a local <aura:iteration> variable, but let’s keep this simple.

Value Providers

After that last section, what’s left to say about value providers? Plenty. But here we’re going to call out one possible source of confusion. Another chute.

Some important features of Lightning components are implemented using value providers. In the preceding expressions examples, we used v. and c. several times. These are the value providers that auto-wire together the component markup, attributes, and controller. In addition to using them in markup, you can use them in controller code. Here are a few lines of an action handler, which uses both the “v.” and “c.” value providers.
({
    "echo" : function(cmp) {
        // ...
        var action = cmp.get("c.serverEcho");
        action.setParams({ echoString : cmp.get("v.message") });

        // ...
    }
})

There are two things to notice. The first is the method used to access the value provider; you have to call get() with the name of the attribute you want to access, including the value provider. So, cmp.get("v.message").

Chute! The second is the chute. Look again at that first line of the function. What is cmp.get("c.serverEcho") getting? It’s getting a reference to the server-side action. In a component’s markup, “c.” represents the client-side controller. In the same component’s JavaScript (action handler or helper), “c.” represents the server-side controller.

Confused? It gets worse. Chute! You’ll also see “c:” in both markup and JavaScript. That’s c-colon, instead of c-period. “c:” is the default namespace. It represents Lightning component code you’ve added to your org.

We recognize there’s an opportunity for confusion, which is why we call it out here. Keep an eye out for “c” in all its forms: “c.”, “c.”, and “c:”.

Global Value Providers

There is one kind of Lightning component value provider—global value providers—that looks like Visualforce global variables. For example, both Visualforce and Lightning components have $Label and $Resource. There are two potential chutes here.

  • Chute! Not every global variable available in Visualforce is available as a global value provider in Lightning components.
  • Chute! Some global variables and global value providers have the same name. Even so, they behave differently. (If you can’t think of reasons why, head back to Lightning Component Core Concepts for a refresher. Before you take the challenge. Hint, hint!)

Don’t try to use a global value provider without reading the documentation for it in the Lightning Components Developer Guide first.

retargeting