How to build a custom lightning component related list with real-time REST data. For this tutorial, I’ll show a technique on how to integrate external data and display the data real-time as a related list in Salesforce. This would not use an external object but a simple custom related list component that uses lightning:datatable base component and a controller than retrieves data via callout to an external REST resource and display them in Salesforce.
This is how it would look like.
For this, I’m calling this a static REST resource that returns the following JSON response.
[ | |
{ | |
"Id": "0d284614-c4ec-424c-a5aa-04e28d06a4df", | |
"Date": "2016-10-14T08:34:10.8+00:00", | |
"RegistryAccountCode": "ABC", | |
"ClientId": 0, | |
"Category": "I", | |
"Description": "Distribution Advice 12102016.pdf", | |
"FileName": "ABC Distribution Advice 12102016.pdf" | |
}, | |
{ | |
"Id": "9924c58a-523a-4b29-a514-1c4d1d7a1d7e", | |
"Date": "2016-07-14T06:33:28.969+00:00", | |
"RegistryAccountCode": "DEF", | |
"ClientId": 0, | |
"Category": "I", | |
"Description": "Distribution Advice 13072016.pdf", | |
"FileName": "DEF Distribution Advice 13072016.pdf" | |
}, | |
{ | |
"Id": "fd07709a-330c-4ad4-9fe7-530928b33a44", | |
"Date": "2017-07-19T00:36:06.213+00:00", | |
"RegistryAccountCode": "CCC", | |
"ClientId": 0, | |
"Category": "I", | |
"Description": "Distribution Advice 14072017.pdf", | |
"FileName": "CCC Distribution Advice 14072017.pdf" | |
}, | |
{ | |
"Id": "7bb16dfc-9e65-4f70-a03b-af0e290e306e", | |
"Date": "2017-01-18T04:33:07.603+00:00", | |
"RegistryAccountCode": "DDD", | |
"ClientId": 0, | |
"Category": "I", | |
"Description": "Distribution Advice 17012017.pdf", | |
"FileName": "DDD Distribution Advice 17012017.pdf" | |
} | |
] |
Next, we need to display this data in a related list in Salesforce. We create a simple lightning component that we can add using Lightning App builder.
Start with the following lightning component markup.
<aura:component implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="dataTableSampleREST"> | |
<!-- attributes --> | |
<aura:attribute name="recordId" type="String"></aura:attribute> | |
<aura:attribute name="mydata" type="Object"></aura:attribute> | |
<aura:attribute name="mycolumns" type="List"></aura:attribute> | |
<aura:attribute name="noResults" type="String"></aura:attribute> | |
<!-- handlers--> | |
<aura:handler name="init" value="{! this }" action="{! c.init }"></aura:handler> | |
<article aura:id="gridContainer" class="slds-card slds-card_boundary"> | |
<lightning:card title="Documents" iconName="standard:document"> | |
<div class="slds-card__header slds-grid"> | |
<aura:if isTrue="{!not(empty(v.mydata))}" > | |
<!-- the container element determine the height of the datatable --> | |
<lightning:datatable keyField="id" | |
data="{! v.mydata }" | |
columns="{! v.mycolumns }" | |
hideCheckboxColumn="true" | |
sortable="false" | |
onrowaction="{!c.getDocument}"></lightning:datatable> | |
</aura:if> | |
<aura:if isTrue="{!empty(v.mydata)}" > | |
<p>{!v.noResults}</p> | |
</aura:if> | |
</div> | |
</lightning:card> | |
</article> | |
</aura:component> |
And controller that calls a helper.
({ | |
init: function (cmp, event, helper) { | |
helper.fetchData(cmp); | |
} | |
}) |
The helper creates a server-side call that creates the REST callout. Then on the successful response, I’m setting the value for the mycolumns attribute by assigning a Javascript object assigning the properties of the column for the datatable. Then I simply assign the mydata attribute assigning and using JSON.parse to turn the response to a Javascript object. With that simple code, I have a related list.
Note: you do not need the var actions as this is for another method I’m working on.
({ | |
fetchData: function (cmp) { | |
var action = cmp.get('c.getDocumentList'); | |
action.setCallback(this, $A.getCallback(function (response) { | |
var state = response.getState(); | |
if (state === "SUCCESS") { | |
if(JSON.parse(response.getReturnValue()) != null) { | |
var actions = [ | |
{ label: 'Download', name: 'download' }, | |
]; | |
cmp.set('v.mycolumns', [ | |
{ | |
label: 'Date', | |
fieldName: 'Date', | |
type: 'date' | |
}, | |
{ label: 'Description', fieldName: 'Description', type: 'text'}, | |
{ label: 'FileName', fieldName: 'FileName', type: 'text'}, | |
{ type: 'action', typeAttributes: { rowActions: actions } } | |
]); | |
cmp.set('v.mydata', JSON.parse(response.getReturnValue())); | |
} else { | |
cmp.set("v.noResults", "No records to display"); | |
} | |
} else if (state === "ERROR") { | |
var errors = response.getError(); | |
console.error(errors); | |
cmp.set("v.noResults", "An error occurred: No records to display"); | |
} | |
})); | |
$A.enqueueAction(action); | |
} | |
}) |
Then for my controller, I have this simple call to my server
public class dataTableSampleREST { | |
@AuraEnabled | |
public static String getDocumentList() { | |
String strEndPoint = 'https://www.lopau.com/rest/accounts'; | |
HttpRequest req = new HttpRequest(); | |
req.setMethod('GET'); | |
req.setEndpoint(strEndPoint); | |
Http h = new Http(); | |
system.debug('## => ' + req); | |
HTTPResponse res = h.send(req); | |
System.debug('## => ' + res.getBody()); | |
if (res.getStatusCode() == 200) { | |
system.debug('## res.getBody() =>' + res.getBody()); | |
return res.getBody(); | |
} | |
return null; | |
} | |
} |
Then I simply drop the component on Lightning App Builder to the related list section for a quick UI match. That should be it.
Recommended Books: