Call Apex from Lightning components

I’ve decided to do some write up on Salesforce – especially Lightning development. Lightning is basically Salesforce’s proprietary JavaScript and CSS Framework bundled into one. It’s a component-based system, mobile friendly, with the power of a server side language (Apex), just in case you need it.

lightning web components

In the following tutorials, you might see a “helper.callServer()” method – which I’m outlining below:

callServer : function(component,method,callback,params) {
        var action = component.get(method);
        if (params) {
            action.setParams(params);
        }
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                // pass returned value to callback function
                callback.call(this,response.getReturnValue());
            } else if (state === "ERROR") {
                // generic error handler
                var errors = response.getError();
                if (errors) {
                    console.log("Errors", errors);
                    if (errors[0] && errors[0].message) {
                        throw new Error("Error" + errors[0].message);
                    }
                } else {
                    throw new Error("Unknown Error");
                }
            }
        });
        $A.enqueueAction(action);
    }

If you’re ever going to do some kind of call to an Apex class – this is a must have in your helper. Think of it as sort of like jQuery’s $.ajax() method – but limited to a specific class.

Salesforce has the same exact code in this doc with some explanation, but I wanted to write it up in my own words. Let’s break it down below.

As mentioned, this is what we need to call an Apex class from our components. It is basically a wrapper to an XMLHttpRequest, along with other utilities to make our JavaScript easier.

Again, components are front end code – Apex sits in the server. This method is the communication between the two.

Set up Apex

First, you declare a class. This is done in our .cmp (component) file, way at the top – it looks like below:

<aura:component implements=”…” controller=”MyClass”>

Now we’re set up with an Apex class called “MyClass”. Let’s build that class, with a method called “doSomething()”:

public with sharing class MyClass{
   @auraEnabled
   public static string doSomething(String input) {
      return input
   }
}

Note the “@auraEnabled” declaration. This allows us to access it from our JavaScript.

With the our helper in place, all we need to do in our controller will be something like below:

helper.callServer(component,"c.doSomething",function(response){
    //INSIDE OUR CALLBACK
    console.log(response) //RESPONSE FROM OUR APEX METHOD
},{})

You see, our helper had arguments that looked like below:

callServer : function(component,method,callback,params) {…

Which is what we’re doing in our controller. The second parameter “c.doSomething” – is the method in our Apex class. The 3rd parameter “callback” – is an anonymous function that get’s triggered through “.apply()” in our helper. This is executed when our Ajax call finishes. And we’ll have access to the response.

Sending Parameters

You can send information to your Apex class by setting an object to the last parameter called “params”. In our example above, we’re simply passing an empty object “{}”. But in reality, you will most likely send something to the server.

Our method “doSomething” is expecting a string called “input”.

The object we can pass will look like below:

On a side note, I've really enjoyed the videos from Laracasts.com. These are high quality web developer tutorials on topics and technologies ranging from Laravel, React, Vue and many more. Head over to Laracasts and check them out!
{
  "input" : "somevalue"
}

Notice the key “input” must match our server variable “input”.

If you would like to pass another value, simply add another key:

{
  "input" : "somevalue",
  "input2" : "somevalue2"
}

In our doSomething method:

doSomething(String input, String input2)

You can also pass multiple values as a JSON string, so in your controller:

var str = JSON.stringify({"input1":"somevalue","input2":"somevalue2"});
var params = {"strsRecord" : str};
helper.callServer(component,"c.doSomething",function(){}, params);

In your Apex class:

doSomething(strsRecord){
   List st = JSON.deserialize(strsRecord);
   System.debug('Here is the params:' +st);

“Promise” Style

In JavaScript, a promise is “an object that may produce a single value some time in the future“. So our helper above is a perfect example of this. Let’s rewrite it using a promise, so we can use it more efficiently, and elegantly.

By this, I mean avoiding “callback” hell. See, callbacks are okay if we’re dealing with a single call. But if we were to make multiple nested calls (especially one that needs relies on the first response etc), it gets ugly real fast like below: 

Callback hell:

helper.callServer(component,"c.doSomething1",function(response1){
     helper.callServer(component,"c.doSomething2",function(response2){
         helper.callServer(component,"c.doSomething3",function(response3){
               //THIS GETS UGLY...
          },{})
     },{})
},{})

So let’s convert it to use a JavaScript promise instead:

callServer : function(component,method,params) {     //PROMISE BASED
        var promiseObj = new Promise(
            function(resolve, reject){
                var action = component.get(method);
                if (params) {
                    action.setParams(params);
                }
                action.setCallback(this,function(response) {
                    var state = response.getState();
                    if (state === "SUCCESS") {
                        var data = response.getReturnValue();
                        resolve(data)
                    } else if (state === "ERROR") {
                        var errors = response.getError();
                        console.log(errors);
                        reject(errors);
                    }
                });
                $A.enqueueAction(action);
            }
        );
        return promiseObj;
    }

As you can see above, there are no more callbacks being passed. All we need are the 3 parameters: “component”, “method” and “params”.

Now we can use this like below:

helper.callServer(component,"c.doSomething",{}).then(function(response){
   console.log(response)
})

You see the use of “.then()”. We’re no longer restricted to a single callback function we were previously. We can even use multiple .then() methods all over our code:

var ajax = helper.callServer(component,"c.doSomething",{});
//first .then()
ajax.then(function(response){
   console.log('do something here');
})
//second.then()
ajax.then(function(response){
   console.log('do more stuff here');
})

We can also chain Promise methods like so:

var ajax = helper.callServer(component,"c.doSomething",{});
ajax.then(function(response){
   console.log(response);
}).catch(function(error){
   console.log(error)
}).finally(function(){
   console.log('this always runs')
})

As you can see, the “Promise” style of the helper can help you write more efficient code.

So keep this in your Lightning helper, in order to communicate with Apex. Its almost always guaranteed to be used at least once in your Salesforce applications.

affiliate link arrowNavan Travel

2 Comments

Leave a Comment.