In todays post, I will be walking you through Lightning Component Methods (a.k.a. Aura Methods) and how they can benefit your applications by simplifying the development process and maximising code reuse.

What is an Aura Method?

Aura Methods is the real name for Lightning Component Methods, so from here onwards I’m going to refer to them as such.

So what are they?

Just like you can define methods inside an apex class and call it from other places in your application, Aura Methods are named pieces of code which can be called from other Lightning Components.

Unlike component events, Aura Methods allow direct communication with components. But a little more on this later.

Basic example

Let’s start off with a basic example to illustrate what Aura Methods are. To illustrate this we’re going to use two Lightning Components; one called Room and the other called Lamp. Like an actual room in a house, the Room component will contain the Lamp component.

Lamp Component

Component

Our Lamp component will display a message that it is switched on if the attribute “isOn” is set to true and if not, display a message it is off. Simple.

To enable the Room component to switch the lamp on and off via toggling, we also include a new Aura Method which will redirect the request to the Lamp’s controller.

<aura:component>

   <aura:attribute name="isOn" type="Boolean" default="false" />

   <aura:method name="toggleLight" action="{!c.toggleLight}" />

   <aura:if isTrue="{!v.isOn}">
      Light is on!
      <aura:set attribute="else">
         Light is off
      </aura:set>
   </aura:if>

</aura:component>

Controller

The controller contains one method to handle the Aura Methods action, “toggleLight”. This method is going to flip the light on and off depending on the Lamps current state. If it’s on, then switch it off, and if it’s off, switch it on. Again, simple.

({
   toggleLight: function(component, event, helper){
      var isOn = component.get('v.isOn');
      component.set('v.isOn', !isOn); // Flip isOn to the opposite value
   }
})

Room component

Now that we have our Lamp component set up, we can now look into building out the Room component which will hold the Lamp and interact with it.

Component

<aura:component>
   <c:Lamp aura:id="lamp" />
   <button onclick="{!c.toggleLightOnLamp}">Toggle light</button>
</aura:component>

In the component we define that we want to use the Lamp component and we also give it an ID so we can access it from the controller. More on this in a moment.

We also include a standard HTML button which when clicked will call the controller to request it to toggle the lamp on or off.

Controller

In the controller we define the action which will handle the onclick event when the HTML button is clicked. The highlighted lines below show how we can find the Lamp component via its ID and also how to directly call the exposed Aura Method.

({
   toggleLightOnLamp: function(component, event, helper){
      var lamp = component.find('lamp');
      lamp.toggleLight();
   }
})

And that’s it! You should at this point have a basic working example illustrating how to use Aura Methods!

Passing arguments

Just as you can define arguments for functions in normal JavaScript methods you can do the same with Aura Methods, but we have to do it in a slightly different approach.

Going back to our Lamp component, we’re going to extend it by allowing the Aura Method to accept an argument which defines whether we should turn the lamp on or off rather than toggling the current state.

<aura:component>

   <aura:attribute name="isOn" type="Boolean" default="false" />

   <aura:method name="toggleLight" action="{!c.toggleLight}">
      <aura:attribute name="turnOn" type="Boolean" />   
   </aura:method>

   <aura:if isTrue="{!v.isOn}">
      Light is on!
      <aura:set attribute="else">
         Light is off
      </aura:set>
   </aura:if>

</aura:component>

Our lamp controller action needs to be updated to retrieve the turnOn attribute value. The highlighted line below shows how to retrieve the argument values which were passed into the Aura Method; we retrieve the values from the arguments parameter.

({
   toggleLight: function(component, event, helper){
      var params = event.getParam('arguments');
      component.set('v.isOn', params.turnOn);
   }
})

We’re now ready to modify our Room component to either switch the lamp on off. First, we need to modify it to include two buttons to set the lamp on or off.

<aura:component>
   <c:Lamp aura:id="lamp" />
   <button onclick="{!c.turnLampOn}">Turn on</button>
   <button onclick="{!c.turnLampOff}">Turn off</button>
</aura:component>

As we now have two buttons defined in the Room component, we now need to add two methods to its controller to handling the onclick events for the two HTML buttons we’ve added.

({
   turnLampOn: function(component, event, helper){
      var lamp = component.find('lamp');
      lamp.toggleLight(true);
   },

   turnLampOff: function(component, event, helper){
      var lamp = component.find('lamp');
      lamp.toggleLight(false);
   }
})

Notice above on the highlighted lines that we set true or false. The order of the attributes defined within the Aura Method inside the Lamp component dictates the order of the values which we pass into the method call.

And that’s all there is to it!

Returning values

The code which runs when an Aura method is called runs synchronously, meaning code execution within the method completes first and then execution of the calling function resumes, nothing runs asychronously. Due to Aura Methods running synchronously they also enable returning of values to the calling function.

Using the same example of the room and the lamp, let’s build out an Aura Method which returns whether the lamp is switched on. First, let’s add a new method called “isSwitchedOn”:

<aura:component>

   <aura:attribute name="isOn" type="Boolean" default="false" />
   
   ...
   
   <aura:method name="isSwitchedOn" action="{!c.isSwitchedOn}" />

</aura:component>

Below is the action which is linked to the Aura Method. Notice the highlighted line, we can return a value just like we would in a normal JavaScript function!

({
   // ...

   isSwitchedOn: function(component, event, helper){
      var isOn = component.get('v.isOn');
      return isOn;
   }
})

Now we can go back to the Room components controller and add in a new controller action to toggle the light on and off as we did in the first example:

({
   toggleLight: function(component, event, helper){
      var lamp = component.find('lamp');
      
      if(lamp.isSwitchedOn()){
         lamp.toggleLight(false);
      } else {
         lamp.toggleLight(true);
      }
   }
})

What’s the difference between them and component events?

Component events are super useful within the framework. They allow parent components to listen out for events in a few different ways:

  • Defining a handler in the parent component to listen out for any component event.
  • Redirecting the component as an attribute to a controller action.
  • Dynamically attaching event handlers to components at runtime to listen out for fired events.

Aura Methods on the other hand don’t allow any of the above. Using Aura Methods are used for direct communication with other Lightning Components. You must have a direct reference to the Lightning component which defines the Aura method in order to call it. Unlike component events though, Aura Methods can now return values. This brings us nicely into the next part, reusing functionality.

Reusing functionality

In our small example we’ve shown how to create a Lamp component which could be used anywhere within our application. We could if we want is to have a lamp in a metophorical kitchen, living room or even a bathroom component. We can reuse it where ever we want to!

We can extend this out to logical blocks within our application too. For example, we could have some Lightning Components which provide the following:

  • Common set of form validation methods. E.g. a place where we can store methods for validating form values, such as isEmailValid.
  • Maintaining state across multiple Lightning Components in a central location.
  • Much more!

Handling asynchronous code in Aura Methods

Quite frequently we need to call a piece of code which needs to perform something asynchronously and then do something with the result.

There are two approaches we can use with Aura Methods:

  • Passing a callback method as an argument value.
  • Return a promise.

If these approaches aren’t suitable in your use case, then you might want to switch to component events or even application events.

Passing a callback function

Callback functions are blocks of code which we want to run only after the asynchronous piece of code has ran.

Let’s run through a new example building on our Lamp component. We’re going to extend our Aura Method to accept a callback function as an argument and this callback function will be fired asynchronously, perhaps after making a callout to the server.

This time we’re going to add a new method to check if the lamp can be switched on based on whether the server tells us we can or not. The call to the server runs asynchronously.

So lets start with the server side controller first. It’s a simple method which states that if it’s past 8pm in the evening then the user is authorised to switch the lamp on 🙂

public class LampController {
   
   @AuraEnabled
   public static Boolean isAuthorised(){
      return System.now().hour() > 20;
   }

}

Below is our new Aura Method inside the Lamp component. This time on our new method we’re going to add in a new attribute to allow us to pass along a callback function which will run after the call to the server has completed.

<aura:component controller="LampController" >

   <aura:method name="checkIfAllowed">
      <aura:attribute name="callback" type="Function" />
   </aura:method>

</aura:component>

Below is the new controller action to be added to the Lamp component. The highlighted lines below show how to extract the callback function from the arguments and also how to call the callback function after the call to the server completes.

({
   checkIfAllowed: function(component, event, helper){
      var action = component.get('c.isAuthorised');
      var params = event.getParam('arguments');
      var callback = params.callback;

      action.setCallback(this, function(response){
         if(response.getState() == 'SUCCESS'){
            callback( response.getReturnValue() );
         } else {
            alert('Failed to check if we can switch on the Lamp!');
         }
      });

      $A.enqueueAction(action);
   }
})

Everything is now in place for us to now us our newly added method in our Lamp component. Lets now go back to our Room component and call the new checkIfAllowed method and pass in a callback function.

({
   toggleLight: function(component, event, helper){
      var lamp = component.find('lamp');
      
      lamp.checkIfAllowed(function(isAllowed){

         lamp.toggleLight(isAllowed);
         
      });
   }
})

So what is happening?

  1. Room component toggleLight method gets called.
  2. toggleLight action asks the Lamp component to check if the user is allowed to switch on the lamp.
  3. Lamp component runs an asynchronous process to check on the server whether the user is authorised.
  4. Response from the server is completed.
  5. Callback function passed in is now called and the result from the call to the server is passed in as an argument.

Returning a promise

An alternative to callback functions is using promises. Fundamentally they are the same as using callback functions, but the key difference being is clarity of the code and avoiding the hell of nested callbacks!

In a future blog post I will cover Promises more and how you can utilise them within your Lightning Components. I promise 😀

A great place to start though is to check out the blog post over at the developers blog from Google which explains more about Promises and how they can benefit your workflow in JavaScript.

A little shortcut

When defining an Aura method inside a Lightning component I’ve shown in all of the examples above that you must specify the action inside the controller, but you don’t have to.

Huh?

If you do not specify the controller action which should handle the Aura method call then it will default to the name of the Aura method. Take a look at this example:

<aura:component>

   <aura:method name="doSomething" />

</aura:component>

Notice that we didn’t specify the action? We don’t need to. If the action is not specified it will search the controller for an action with the same name.

({
   doSomething: function(component, event, helper){
      // This action would be called
   }
})

I’m not saying that this is the preferred approach, I personally prefer clarity inside the code over not so known conventions like the above.

To conclude

Aura Methods are extremely useful part of the Lightning Component framework and I encourage you to utilise them within your application!

Some useful links for further reading: