Aura framework provides a javascript action function to send a request from the lightning component to apex controller and it returns the response back to the client side. Please refer this link to know how the server side action is handled by the client-side controller. In this blog we are explaining the best practices can be followed to do this communication.
Implementation
This implementation requires two components. The server communication is modularized into an abstracted component which is then extended to the second component as needed.
Abstract Component
<aura:component abstract="true" extensible="true" access="global" > | |
{!v.body} | |
</aura:component> |
({ | |
runServerMethod : function (component, serverMethodName, successCallBack, failureCallback, params ) { | |
var self = this; | |
var action = component.get(serverMethodName); | |
if (params) { | |
action.setParams(params); | |
} | |
action.setCallback( this, function (response) { | |
var state = response.getState(); | |
if (state === "SUCCESS") { | |
successCallBack.call(this,response); | |
} else if (state === "INCOMPLETE") { | |
// show a toast or create a callback to control this state as well. | |
console.log("Failed to connect Salesforce!!"); | |
}else if (state === "ERROR") { | |
var errors = response.getError(); | |
if (!errors) { | |
errors = [{"message" : "Unknown Error Occured"}]; | |
} | |
failureCallback.call(this,errors); | |
} | |
}); | |
$A.enqueueAction(action); | |
} | |
}) |
- runServerMethod – helper method defined in the AbstractBaseHelper.js file, to interact with the apex controller method.
- Method Parameters
- component – default parameter in the js controller
- serverMethodName – the name of the server method in the following format, namespace.method_name, eg: c.callApexControllerMethod
- successCallBack – the callback executes for a successful server transaction
- failureCallback – the callback executes for a failed transaction
- params – parameters to be passed to the apex controller method.
response.getState() – provides the action status of the call happened from the client side to server side. The possible action states are NEW, RUNNING, SUCCESS, ERROR, INCOMPLETE and ABORTED.
Refer the link for more details: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_actions_states.htm
You may have noticed that call method is invoked with two parameters in successCallback and failureCallback. The call is a seeded prototype method of vanilla javascript to invoke the function by passing the parameters. Please refer to the link given in the below reference section for details.
Sub Component
The ChildComponent is extended from the AbstractBase component so the subcomponent will have access to all the helper methods of the parent. The sub-component layout consists of input, checkbox and a button control. In addition to that, a couple of aura attributes are defined to store the values of the HTML controls and server responses.
c.sentMessage is a controller event which is triggered by the ‘send message’ button click which is used for invoking the helper method defined in the childComponent.
<aura:component extends="c:AbstractBase" controller="TestApexController"> | |
<aura:attribute name="message" type="String" default=""/> | |
<aura:attribute name="serverMessage" type="String" default="" description="server message assigns to this"/> | |
<aura:attribute name="showError" type="Boolean" default="false" /> | |
<aura:attribute name="showServerError" type="Boolean" default="false" /> | |
<ui:inputText label="Message" value="{!v.message}" /> | |
<lightning:input type="checkbox" label="Show Error" name="showErrorCheck" checked="{!v.showError}"/> | |
<lightning:button variant="brand" label="Send Message" onclick="{! c.sendMessage }" /> | |
<br/><br/><br/> | |
<aura:if isTrue="{!v.showServerError}"> | |
Server Message : {!v.serverMessage} | |
<aura:set attribute="else"> | |
Server Message : {!v.serverMessage} | |
</aura:set> | |
</aura:if> | |
</aura:component> |
({ | |
sendMessage : function(component, event, helper) { | |
helper.sendMessage(component,helper); | |
} | |
}) |
({ | |
sendMessage : function (component,helper) { | |
var message = component.get("v.message"); | |
var showError = component.get("v.showError"); | |
var param = {"message":message,"showError":showError}; | |
helper.runServerMethod(component,"c.callApexControllerMethod",function(response){ | |
component.set("v.serverMessage",response.getReturnValue()); | |
}, function(errors) { | |
component.set("v.showServerError",true); | |
component.set("v.serverMessage",errors[0].message); | |
},param); | |
console.log(message,showError); | |
} | |
}) |
The sendMessage method defined in the helper part of aura bundle is invoked from the controller part. The helper method calls the runServerMethod which is defined in the parent abstract component.
runServerMethod is invoked with the following parameters.
- component
- callApexControllerMethod – static method defined in the apex controller, TestApexController
- success callback – sets the serverMessage attribute with the response message from the server.
- failure callback – set the showServerError, serverMessage attributes with the server response.
- param – Collection of input control values – {“message“:message,“showError“:showError};
- message – the value of the input textbox
- showError – checked or unchecked status as a boolean
TestApexController
The apex method mush have the following attributes.
- static and public keywords
- @AuraEnabled annotation
public class TestApexController { | |
@AuraEnabled | |
public static String callApexControllerMethod ( String message, Boolean showError ) { | |
String counterMessage = 'Response from apex controller – ' + 'Your Message : ' + message; | |
if (showError) { | |
throw new AuraHandledException('Custom Exception from the apex controller'); | |
} | |
return counterMessage; | |
} | |
} |
The apex method accepts two parameters and returns a string message. The method throws an aura exception if the ‘showError’ parameter value is true
Testing Application
ChildComponent is invoked from the application markup.
<aura:application > | |
<c:ChildComponent /> | |
</aura:application> |
Calling a Server-Side Action
A client-side controller is a JavaScript object in object-literal notation containing a map of name-value pairs.
Let’s say that you want to trigger a server-call from a component. The following component contains a button that’s wired to a client-side controller echo action. SimpleServerSideController contains a method that returns a string passed in from the client-side controller.
<aura:component controller="SimpleServerSideController">
<aura:attribute name="firstName" type="String" default="world"/>
<lightning:button label="Call server" onclick="{!c.echo}"/>
</aura:component>
This client-side controller includes an echo action that executes a serverEcho method on a server-side controller.
Tip
Use unique names for client-side and server-side actions in a component. A JavaScript function (client-side action) with the same name as an Apex method (server-side action ) can lead to hard-to-debug issues. In debug mode, the framework logs a browser console warning about the clashing client-side and server-side action names.
({
"echo" : function(cmp) {
// create a one-time use instance of the serverEcho action
// in the server-side controller
var action = cmp.get("c.serverEcho");
action.setParams({ firstName : cmp.get("v.firstName") });
// Create a callback that is executed after
// the server-side action returns
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
// Alert the user with the value returned
// from the server
alert("From server: " + response.getReturnValue());
// You would typically fire a event here to trigger
// client-side notification that the server-side
// action is complete
}
else if (state === "INCOMPLETE") {
// do something
}
else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " +
errors[0].message);
}
} else {
console.log("Unknown error");
}
}
});
// optionally set storable, abortable, background flag here
// A client-side action could cause multiple events,
// which could trigger other events and
// other server-side action calls.
// $A.enqueueAction adds the server-side action to the queue.
$A.enqueueAction(action);
}
})
In the client-side controller, we use the value provider of c to invoke a server-side controller action. We also use the c syntax in markup to invoke a client-side controller action.
The cmp.get("c.serverEcho") call indicates that we’re calling the serverEcho method in the server-side controller. The method name in the server-side controller must match everything after the c. in the client-side call. In this case, that’s serverEcho.
The implementation of the serverEcho Apex method is shown in Apex Server-Side Controller Overview.
Use action.setParams() to set data to be passed to the server-side controller. The following call sets the value of the firstName argument on the server-side controller’s serverEcho method based on the firstName attribute value.
action.setParams({ firstName : cmp.get("v.firstName") });
action.setCallback() sets a callback action that is invoked after the server-side action returns.
action.setCallback(this, function(response) { ... });
The server-side action results are available in the response variable, which is the argument of the callback.
response.getState() gets the state of the action returned from the server.
Note
You don’t need a cmp.isValid() check in the callback in a client-side controller when you reference the component associated with the client-side controller. The framework automatically checks that the component is valid.
response.getReturnValue() gets the value returned from the server. In this example, the callback function alerts the user with the value returned from the server.
$A.enqueueAction(action) adds the server-side controller action to the queue of actions to be executed. All actions that are enqueued will run at the end of the event loop. Rather than sending a separate request for each individual action, the framework processes the event chain and batches the actions in the queue into one request. The actions are asynchronous and have callbacks.
Tip
If your action isn’t executing, make sure that you’re not executing code outside the framework’s normal rerendering lifecycle. For example, if you use window.setTimeout() in an event handler to execute some logic after a time delay, wrap your code in $A.getCallback(). You don't need to use $A.getCallback() if your code is executed as part of the framework's call stack; for example, your code is handling an event or in the callback for a server-side controller action.
Client Payload Data Limit
Use action.setParams() to set data for an action to be passed to a server-side controller.
The framework batches the actions in the queue into one server request. The request payload includes all of the actions and their data serialized into JSON. The request payload limit is 4 MB.
- Action States
Call a server-side controller action from a client-side controller. The action can have different states during processing.
Function.prototype.call()
The call() method calls a function with a given this value and arguments provided individually.
call()
call(thisArg)
call(thisArg, arg1)
call(thisArg, arg1, arg2)
call(thisArg, arg1, ... , argN)
Copy to ClipboardParameters
The value to use as this when calling func.
Note: In certain cases, thisArg may not be the actual value seen by the method.
If the method is a function in non-strict mode, null and undefined will be replaced with the global object, and primitive values will be converted to objects.
Arguments for the function.
Return value
The result of calling the function with the specified this value and arguments.
Description
The call() allows for a function/method belonging to one object to be assigned and called for a different object.
call() provides a new value of this to the function/method. With call(), you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.
Note: While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.
Examples
Using call() to chain constructors for an object
You can use call to chain constructors for an object (similar to Java).
In the following example, the constructor for the Product object is defined with two parameters: name and price.
Two other functions, Food and Toy, invoke Product, passing this, name, and price. Product initializes the properties name and price, both specialized functions define the category.
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);
Copy to ClipboardUsing call() to invoke an anonymous function
In this example, we create an anonymous function and use call to invoke it on every object in an array.
The main purpose of the anonymous function here is to add a print function to every object, which is able to print the correct index of the object in the array.
Note: Passing the object as this value is not strictly necessary, but is done for explanatory purpose.
const animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];
for (let i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
Copy to ClipboardUsing call() to invoke a function and specifying the context for 'this'
In the example below, when we call greet, the value of this will be bound to object obj.
function greet() {
const reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
console.log(reply);
}
const obj = {
animal: 'cats', sleepDuration: '12 and 16 hours'
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
Copy to ClipboardUsing call() to invoke a function and without specifying the first argument
In the example below, we invoke the display function without passing the first argument. If the first argument is not passed, the value of this is bound to the global object.
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // sData value is Wisen
Copy to ClipboardNote: In strict mode, the value of this will be undefined. See below.
'use strict';
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // Cannot read the property of 'sData' of undefined
Copy to ClipboardSpecifications
Specification
ECMAScript Language Specification # sec-function.prototype.call |
Browser compatibility
desktopmobileserverChromeEdgeFirefoxInternet ExplorerOperaSafariWebView AndroidChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetDenoNode.jscall
1
|
12
|
1
|
5.5
|
4
|
1
|
1
|
18
|
4
|
10.1
|
1
|
1.0
|
1.0
|
0.10.0
footnote
Toggle history |
Legend
'스타 블로그' 카테고리의 다른 글
Custom Lightning Page Template / Layout (0) | 2022.04.16 |
---|---|
SFDX – Salesforce Command Line Interface (CLI) Commands (0) | 2022.04.16 |
쿠리야마 리오 인★ 화보같은 사진 모음 (0) | 2022.04.08 |
DevOps (0) | 2022.03.13 |
강한나 인★ 화보같은 사진 모음 (0) | 2022.03.09 |