Lightning Components and Custom Apex Classes
Overview
This week I’ve been generating summary information in an Apex controller and surfacing this through a Lightning Component. When designing the solution, my initial thoughts were that I’d either:
- have the component call multiple methods on the controller - not as inefficient as it sounds thanks to ‘boxcarring’, described in detail in Peter Chittum’s blog post.
- return the results as a JSON string and parse this client side to access the details
However, after looking through the Lightning Components Developer’s Guide, a third way presented itself - the framework allows the Apex controller to return a instance of a custom Apex class, which is then automatically converted into a JavaScript object for use client-side.
Scenario
For the purposes of this blog post I have a simple use-case of returning the total number of Accounts, Contacts and Opportunities in the system.
Code
The summary information is encapsulated in the RecordCounts custom Apex class, which also doubles as the Apex controller for the component, providing the GetRecordCounts method to retrieve the information. Note that the methods and attributes for use client-side have the AuraEnabled annotation:
public class RecordCounts { @AuraEnabled public Integer numAccounts {get; set;} @AuraEnabled public Integer numContacts {get; set;} @AuraEnabled public Integer numOpportunities {get; set;} @AuraEnabled public static RecordCounts GetRecordCounts() { RecordCounts result=new RecordCounts(); result.numAccounts=[select count() from Account]; result.numContacts=[select count() from Contact]; result.numOpportunities=[select count() from Opportunity]; return result; } }
The lightning component is very straightforward - it defines that the Apex controller is ‘RecordCounts’, provides an attribute to store the retrieved record count instance in and has markup to output the value. The information is retrieved from the server via the doInit event handler, which will be invoked when the component is initialised but before it is rendered.
<aura:component controller="RecordCounts"> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <aura:attribute type="RecordCounts" name="counts" /> Number of accounts = {!v.counts.numAccounts}<br/> Number of contacts = {!v.counts.numContacts}<br/> Number of opportunities = {!v.counts.numOpportunities}<br/> </aura:component>
Note that the type of the ‘counts’ attribute is defined as the name of the custom apex class - RecordCounts. Note also that I can simply access properties from the Apex class using the JavaScript object dot notation, as the record instance has been converted to a Javascript object representation.
In accordance with Lightning Components best practice, the component controller simply delegates to a helper for the init event callback handler:
({ doInit : function(component, event, helper) { helper.doInit(component, event); } })
while the helper executes the server side method and sets the Javascript object representation of the Apex class instance into the ‘counts’ attribute upon success without any intervention from me to process the result or translate it to something that the component can use directly, as this is all handled by the framework:
({ doInit : function(cmp, ev) { var action = cmp.get("c.GetRecordCounts"); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { cmp.set('v.counts', response.getReturnValue()); } else if (state === "ERROR") { alert('Error : ' + JSON.stringify(errors)); } }); $A.enqueueAction(action); } })
Adding this component to a Lightning application and executing it generates the following output: