When we use an Apex Controller method in lightning JS Controller or Helper, sometimes error occurs on execution of apex method. In lightning response object though the state value comes as ERROR but the message in the error object always says ‘Internal Server Error”. Here is an example to handle the apex exception and how to show custom messages in Lightning Component.
In below example I’ve used Lead object FirstName, LastName, Email & Company Field. In lead object LastName & Company fields are required. If we will submit the form without the required fields, then the apex method will throw the error message, which we can show in lightning component or we can add our custom message there.
Apex Controller:
public class SampleAuraController {
@AuraEnabled
Public static void createLead(Lead objLead){
try{
//Insert Lead Record
insert objLead;
}catch(DmlException e) {
//get DML exception message
throw new AuraHandledException(e.getMessage());
}catch(Exception e){
//get exception message
throw new AuraHandledException(e.getMessage());
}
finally {
}
}
}
Lightning Component:
<!--Sample.cmp-->
<aura:component controller="SampleAuraController" implements="flexipage:availableForAllPageTypes,force:appHostable">
<!--Declare Attributes-->
<aura:attribute name="objLead" type="Lead" default="{'sobjectType':'Lead',
'FirstName': '',
'LastName': '',
'Email': '',
'Company': ''}"/>
<!--Component Start-->
<div class="slds-m-around--xx-large">
<div class="container-fluid">
<div class="form-group">
<lightning:input name="fname" type="text" maxlength="50" label="First Name" value="{!v.objLead.FirstName}" />
</div>
<div class="form-group">
<lightning:input name="lname" type="text" maxlength="50" label="Last Name" value="{!v.objLead.LastName}" />
</div>
<div class="form-group">
<lightning:input name="emailId" type="email" maxlength="100" label="Email" value="{!v.objLead.Email}" />
</div>
<div class="form-group">
<lightning:input name="company" type="text" maxlength="50" label="Company" value="{!v.objLead.Company}" />
</div>
</div>
<br/>
<lightning:button variant="brand" label="Submit" onclick="{!c.handleLeadSave}" />
</div>
<!--Component End-->
</aura:component>
Lightning JS Controller:
({
//Handle Lead Save
handleLeadSave : function(component, event, helper) {
var objLead = component.get("v.objLead");
var action = component.get("c.createLead");
action.setParams({
objLead : objLead
});
action.setCallback(this,function(a){
var state = a.getState();
if(state === "SUCCESS"){
alert('Record is Created Successfully');
} else if(state === "ERROR"){
var errors = action.getError();
if (errors) {
if (errors[0] && errors[0].message) {
alert(errors[0].message);
}
}
}else if (status === "INCOMPLETE") {
alert('No response from server or client is offline.');
}
});
$A.enqueueAction(action);
}
})
Output:
LastName Required Field Error Message:
Loading...
Lightning Component:
<!--
Name: ContactList.cmp
-->
<aura:component controller="ContactController">
<!--Declare Event Handlers-->
<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
<!--Declare Attributes-->
<aura:attribute name="contactList" type="ContactController.ContactWrapper[]" />
<aura:attribute name="isSelectAll" type="boolean" default="false"/>
<div class="slds-m-around_xx-large">
<h1 class="slds-text-heading--medium">Contacts</h1>
<br/>
<!--Contact List Table-->
<table class="slds-table slds-table--bordered slds-table--cell-buffer" role="grid">
<thead>
<tr class="slds-text-title--caps">
<th>
<label class="slds-checkbox">
<ui:inputCheckbox value="{!v.isSelectAll}" change="{!c.handleSelectAllContacts}" aura:id="selectAll"/>
<span class="slds-checkbox--faux" />
<span class="slds-form-element__label"></span>
</label>
</th>
<th scope="col">
<div class="slds-truncate" title="Name">Name</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Account">Account</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Phone">Phone</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Email">Email</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.contactList}" var="con">
<tr>
<th>
<label class="slds-checkbox">
<ui:inputCheckbox aura:id="checkContact" value="{!con.isSelected}" text="{!con.Id}"/>
<span class="slds-checkbox--faux" />
<span class="slds-form-element__label"></span>
</label>
</th>
<th scope="row">
<div class="slds-truncate" title="{!con.Name}">{!con.Name}</div>
</th>
<td>
<div class="slds-truncate" title="{!con.Account}">{!con.Account}</div>
</td>
<th scope="row">
<div class="slds-truncate" title="{!con.Phone}">{!con.Phone}</div>
</th>
<td>
<div class="slds-truncate" title="{!con.Email}">{!con.Email}</div>
</td>
</tr>
</aura:iteration>
</tbody>
</table>
<div>
<br/>
<lightning:button label="Submit" class="slds-button_brand" onclick="{!c.handleSelectedContacts }" />
</div>
</div>
</aura:component>
Lightning JS Controller:
({
//get Contact List from apex controller
doInit : function(component, event, helper) {
var action = component.get("c.getContactList");
action.setCallback(this, function(result){
var state = result.getState();
if (component.isValid() && state === "SUCCESS"){
component.set("v.contactList",result.getReturnValue());
}
});
$A.enqueueAction(action);
},
//Select all contacts
handleSelectAllContacts: function(component, event, helper) {
var getID = component.get("v.contactList");
var checkvalue = component.find("selectAll").get("v.value");
var checkContact = component.find("checkContact");
if(checkvalue == true){
for(var i=0; i<checkContact.length; i++){
checkContact[i].set("v.value",true);
}
}
else{
for(var i=0; i<checkContact.length; i++){
checkContact[i].set("v.value",false);
}
}
},
//Process the selected contacts
handleSelectedContacts: function(component, event, helper) {
var contactList = component.get("v.contactList");
var isSelectAll = component.get("v.isSelectAll");
var selectedContacts = [];
if(isSelectAll){
selectedContacts = contactList;
}
else{
var k = 0;
for (var i=0; i<contactList.length; i++){
var c = contactList[i];
if(c.isSelected) {
selectedContacts[k] = c;
k++;
}
}
}
if(selectedContacts.length > 0){
var contactRecords = JSON.stringify(selectedContacts);
var action = component.get("c.processSelectedContacts");
action.setParams({
contactRecords : contactRecords
});
action.setCallback(this, function(result){
var state = result.getState();
if (component.isValid() && state === "SUCCESS"){
alert('Success in calling server side action');
}
else if(state == "ERROR"){
alert('Error in calling server side action');
}
});
$A.enqueueAction(action);
}
}
})
Apex Controller:
public class ContactController {
@AuraEnabled
Public static List<ContactWrapper> getContactList(){
List<ContactWrapper> contactList = new List<ContactWrapper>();
//get all contact list
List<Contact> conList = [SELECT Id, Name, Account.Name, Phone, Email FROM Contact LIMIT 10];
for(Contact con : conList){
ContactWrapper obj = new ContactWrapper();
obj.ContactId = con.Id;
obj.Name = con.Name;
obj.Account = con.Account.Name;
obj.Phone = con.Phone;
obj.Email = con.Email;
obj.isSelected = false;
contactList.add(obj);
}
return contactList;
}
@AuraEnabled
Public static void processSelectedContacts(string contactRecords){
system.debug('contactRecords-' + contactRecords);
List<ContactWrapper> contactList = new List<ContactWrapper>();
if(!string.isBlank(contactRecords)){
contactList = (List<ContactWrapper>)System.JSON.deserialize(contactRecords,List<ContactWrapper>.class);
system.debug('contactList-' + contactList);
}
}
public class ContactWrapper{
@AuraEnabled
public String ContactId {get;set;}
@AuraEnabled
public String Name {get;set;}
@AuraEnabled
public String Account {get;set;}
@AuraEnabled
public String Phone {get;set;}
@AuraEnabled
public String Email {get;set;}
@AuraEnabled
public boolean isSelected {get;set;}
}
}
Loading...
Sample Component:
<!--
Name: Sample.cmp
-->
<aura:component >
<div class="slds-m-around_xx-large">
<label class="mdp-form-user-element__label" id="enteredName"></label><br/><br/>
<lightning:button label="Add Your Name" variant="brand" onclick="{!c.handlePopup}"/>
</div>
{!v.body }
</aura:component>
Sample Component JS Controller:
({
handlePopup : function(component, event,helper) {
//Create Dynamic Component
$A.createComponent('c:SampleModalPopup', {
title: 'Please enter your name',
}, function attachModal(modalCmp, status) {
if (component.isValid() && status === 'SUCCESS') {
var body = component.get("v.body");
body.push(modalCmp);
component.set("v.body", body);
}
});
}
})
ModalPopup Component:
<!--
Name: ModalPopup.cmp
-->
<aura:component >
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:attribute name="title" type="String" />
<div aura:id="modalDiv">
<div role="dialog" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<div class="slds-modal__header">
<button class="slds-button slds-modal__close slds-button--icon-inverse" title="Close" onclick="{!c.handleCloseModal}">
X<span class="slds-assistive-text">Close</span>
</button>
<h1 class="slds-text-heading--medium">{!v.title}</h1>
</div>
<!--Modal Box Header-->
<div class="slds-modal__content slds-p-around--medium">
<input type="text" placeholder="Please enter your name" id="userName" autofocus="autofocus" class="slds-input"/>
</div>
<!--Modal Box Button-->
<div class="slds-modal__footer">
<lightning:button label="Submit" class="slds-button_brand" onclick="{!c.handleSubmit}" />
<lightning:button label="Cancel" class="slds-button" onclick="{!c.handleCloseModal }" />
</div>
</div>
</div>
<div class="slds-backdrop slds-backdrop--open"></div>
</div>
</aura:component>
ModalPopup JS Controller:
({
doInit : function(component, event, helper) {
console.log('Modal Popup Load');
},
handleSubmit : function(component, event, helper){
var userName = document.getElementById("userName");
var enteredName = document.getElementById("enteredName");
enteredName.innerHTML = userName.value;
var popupWindow = component.find('modalDiv').getElement();
if(popupWindow){
popupWindow.style.display = 'none';
}
},
handleCloseModal : function(component, event, helper){
var popupWindow = component.find('modalDiv').getElement();
if(popupWindow){
popupWindow.style.display = 'none';
}
}
})
Output:
Loading...
Here is an example of Lightning Contact List data table with multiple checkbox select option.
Apex Controller:
public class ContactAuraController {
@AuraEnabled
Public static List<Contact> getContactList(){
//get all contact list
List<Contact> conList = [SELECT Id, Name, Account.Name, Phone, Email FROM Contact LIMIT 10];
return conList;
}
}
Component:
<!--
Name: ContactList.cmp
-->
<aura:component controller="ContactAuraController">
<!--Declare Event Handlers-->
<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
<!--Declare Attributes-->
<aura:attribute name="contactList" type="list" />
<aura:attribute name="isSelectAll" type="boolean" default="false"/>
<div class="slds-m-around_xx-large">
<h1 class="slds-text-heading--medium">Contacts</h1>
<br/>
<!--Contact List Table-->
<table class="slds-table slds-table--bordered slds-table--cell-buffer" role="grid">
<thead>
<tr class="slds-text-title--caps">
<th>
<label class="slds-checkbox">
<ui:inputCheckbox value="{!v.isSelectAll}" change="{!c.handleSelectAllContact}" aura:id="selectAll"/>
<span class="slds-checkbox--faux" />
<span class="slds-form-element__label"></span>
</label>
</th>
<th scope="col">
<div class="slds-truncate" title="Name">Name</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Account">Account</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Phone">Phone</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Email">Email</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.contactList}" var="con">
<tr>
<th>
<label class="slds-checkbox">
<ui:inputCheckbox aura:id="checkContact" value="" text="{!con.Id}"/>
<span class="slds-checkbox--faux" />
<span class="slds-form-element__label"></span>
</label>
</th>
<th scope="row">
<div class="slds-truncate" title="{!con.Name}">{!con.Name}</div>
</th>
<td>
<div class="slds-truncate" title="{!con.Account.Name}">{!con.Account.Name}</div>
</td>
<th scope="row">
<div class="slds-truncate" title="{!con.Phone}">{!con.Phone}</div>
</th>
<td>
<div class="slds-truncate" title="{!con.Email}">{!con.Email}</div>
</td>
</tr>
</aura:iteration>
</tbody>
</table>
<div>
<br/>
<lightning:button label="Submit" class="slds-button_brand" onclick="{!c.handleSelectedContacts }" />
</div>
</div>
</aura:component>
Component JS Controller:
({
//get Contact List from apex controller
doInit : function(component, event, helper) {
var action = component.get("c.getContactList");
action.setParams({
});
action.setCallback(this, function(result){
var state = result.getState();
if (component.isValid() && state === "SUCCESS"){
component.set("v.contactList",result.getReturnValue());
}
});
$A.enqueueAction(action);
},
//Select all contacts
handleSelectAllContact: function(component, event, helper) {
var getID = component.get("v.contactList");
var checkvalue = component.find("selectAll").get("v.value");
var checkContact = component.find("checkContact");
if(checkvalue == true){
for(var i=0; i<checkContact.length; i++){
checkContact[i].set("v.value",true);
}
}
else{
for(var i=0; i<checkContact.length; i++){
checkContact[i].set("v.value",false);
}
}
},
//Process the selected contacts
handleSelectedContacts: function(component, event, helper) {
var selectedContacts = [];
var checkvalue = component.find("checkContact");
if(!Array.isArray(checkvalue)){
if (checkvalue.get("v.value") == true) {
selectedContacts.push(checkvalue.get("v.text"));
}
}else{
for (var i = 0; i < checkvalue.length; i++) {
if (checkvalue[i].get("v.value") == true) {
selectedContacts.push(checkvalue[i].get("v.text"));
}
}
}
console.log('selectedContacts-' + selectedContacts);
}
})
Output:
Loading...