Implementing Lodash in Salesforce

Implementing Lodash in Salesforce

Recently in my project the requirement needed use of large number of arrays. Initially the thought was to iterate over the array elements using for loop, resulting use of large number of for loops and therefore making the overall process slow. So in search of an alternative found a better approach using the JavaScript library called Lodash. Lodash is simple, effective and in few lines we can iterate over all the array elements. In the beginning Lodash was used for removing duplicates, later on for sorting array elements, finding a particular object in an array of objects, etc. This article is to show how to implement Lodash in Salesforce Lightning (same approach can be implemented in Visualforce pages). Before that let’s discuss:

What is Lodash ?

Lodash is a low-level utility library that offers consistency, customization and performance. It makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc. Lodash’s modular methods are great for:

  • Iterating arrays, objects, & strings.
  • Manipulating & testing values.
  • Creating composite functions.

Using Lodash in Sorting Datatables with individual columns:

Below data table displays list of Account details with fields Name, City, Phone and Revenue. Lightning Design System is used for designing the table and Lodash full build library which is uploaded as static resource used for sorting the items. The sorting arrow icons are SVG components, you can follow the trailhead tutorial to get the icons.

screen-shot-2016-09-07-at-11-30-00-am

Following is the controller used to query the list of account details.

AccountClass.apxc:

[sourcecode language=”java”]

public class AccountClass {

@AuraEnabled
public static List<Account> getAccountItems() {

List<Account> accountDetails = [Select Id,Name,BillingCity,Phone,AnnualRevenue from Account];

return accountDetails;
}

}

[/sourcecode]

Lightning component is created to display the queried list of Accounts.

sortingCmp.cmp:

[sourcecode language=”html”]

<aura:component access=”global” controller=”AccountClass” implements=”force:appHostable,flexipage:availableForAllPageTypes”>

<ltng:require styles=”/resource/slds0122/assets/styles/salesforce-lightning-design-system.min.css” />
<ltng:require scripts=”/resource/lodash/lodash/lodash.js” />

<aura:attribute name=”accountItems” type=”Account[]” />
<aura:attribute name=”BItems” type=”Account[]” />
<aura:attribute name=”sort1″ type=”String” default=”down” />
<aura:attribute name=”sort2″ type=”String” default=”down” />
<aura:attribute name=”sort3″ type=”String” default=”down” />
<aura:attribute name=”sort4″ type=”String” default=”down” />

<aura:handler name=”init” value=”{!this}” action=”{!c.doInit}” />
<div class=”slds”>
<div class=”container slds-p-top–medium MyContent”>
<form class=”slds-form–stacked”>
<div id=”contentTable” class=”slds-scrollable–x”>
<table class=”slds-table slds-table–bordered slds-table–cell-buffer”>
<thead>
<tr class=”slds-text-heading–label” style=”background-color: #27ae60″>
<th class=”slds-size–3-of-12″ scope=”col” style=”font-weight: 500;color: white;”>
<div class=”slds-grid slds-wrap”>
<span class=”slds-truncate” style=”padding-top:3px”>Name</span>
<div class=”slds-icon_container” title=”Sort Column”>
<ui:button label=”” class=”slds-button slds-button–icon-bare iconButton” press=”{!c.sortByName}”>
<aura:if isTrue=”{!v.sort1 == ‘down’}”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowdown”>
</c:svg>
<aura:set attribute=”else”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowup”>
</c:svg>
</aura:set>
</aura:if>
</ui:button>
</div>
</div></th>
<th class=”slds-size–3-of-12″ scope=”col” style=”font-weight: 500;color: white;”>
<div class=”slds-grid slds-wrap”>
<span class=”slds-truncate” style=”padding-top:3px”>Billing City</span>
<div class=”slds-icon_container” title=”Sort Column”>
<ui:button label=”” class=”slds-button slds-button–icon-bare iconButton” press=”{!c.sortByCity}”>
<aura:if isTrue=”{!v.sort2 == ‘down’}”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowdown”>
</c:svg>
<aura:set attribute=”else”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowup”>
</c:svg>
</aura:set>
</aura:if>
</ui:button>
</div>
</div></th>
<th class=”slds-size–3-of-12″ scope=”col” style=”font-weight: 500;color: white;”>
<div class=”slds-grid slds-wrap”>
<span class=”slds-truncate” style=”padding-top:3px”>Phone</span>
<div class=”slds-icon_container” title=”Sort Column”>
<ui:button label=”” class=”slds-button slds-button–icon-bare iconButton” press=”{!c.sortByPhone}”>
<aura:if isTrue=”{!v.sort3 == ‘down’}”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowdown”>
</c:svg>
<aura:set attribute=”else”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowup”>
</c:svg>
</aura:set>
</aura:if>
</ui:button>
</div>
</div></th>
<th class=”slds-size–3-of-12″ scope=”col” style=”font-weight: 500;color: white;”>
<div class=”slds-grid slds-wrap”>
<span class=”slds-truncate” style=”padding-top:3px”>Annual Revenue</span>
<div class=”slds-icon_container” title=”Sort Column”>
<ui:button label=”” class=”slds-button slds-button–icon-bare iconButton” press=”{!c.sortByRevenue}”>
<aura:if isTrue=”{!v.sort4 == ‘down’}”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowdown”>
</c:svg>
<aura:set attribute=”else”>
<c:svg ariaHidden=”true” class=”slds-button__icon iconSVGButton”
xlinkHref=”/resource/slds0122/assets/icons/utility-sprite/svg/symbols.svg#arrowup”>
</c:svg>
</aura:set>
</aura:if>
</ui:button>
</div>
</div></th>
</tr>
</thead>
<tbody>
<aura:iteration items=”{!v.accountItems}” var=”Item” indexVar=”index”>
<tr>
<td class=”slds-size–3-of-12″>{!Item.Name}</td>
<td class=”slds-size–3-of-12″>{!Item.BillingCity}</td>
<td class=”slds-size–3-of-12″>{!Item.Phone}</td>
<td class=”slds-size–3-of-12″>$ {!Item.AnnualRevenue}</td>
</tr>
</aura:iteration></tbody>
</table>
</div>
</form>
</div>
</div>
</aura:component>

[/sourcecode]

Clicking on the arrow icons triggers javascript functions in the client side controller, Lodash sorting methods are implemented here.

sortingCmpController.js:

[sourcecode language=”javascript”]

({
doInit : function(component) {
var action = component.get(“c.getAccountItems”);
action.setCallback(this, function(a) {
if (a.getState() === “SUCCESS”) {
var uniqueItems = _.orderBy(a.getReturnValue(), function(x){
return x.Name;
},[‘asc’]);
component.set(“v.accountItems”, uniqueItems);
} else if (a.getState() === “ERROR”) {
$A.log(“Errors”, a.getError());
}
});
$A.enqueueAction(action);
},

sortByName : function(component) {
var items = component.get(“v.accountItems”);
if(component.get(“v.sort1”) === “down”){
var uniqueItems = _.orderBy(items, function(x){
return x.Name;
},[‘desc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort1”, “up”);
} else {
var uniqueItems = _.orderBy(items, function(x){
return x.Name;
},[‘asc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort1”, “down”);
}
},

sortByCity : function(component) {
var items = component.get(“v.accountItems”);
if(component.get(“v.sort2”) === “down”){
var uniqueItems = _.orderBy(items, function(x){
return x.BillingCity;
},[‘desc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort2”, “up”);
} else {
var uniqueItems = _.orderBy(items, function(x){
return x.BillingCity;
},[‘asc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort2”, “down”);
}
},

sortByPhone : function(component) {
var items = component.get(“v.accountItems”);
if(component.get(“v.sort3”) === “down”){
var uniqueItems = _.orderBy(items, function(x){
return x.Phone;
},[‘desc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort3”, “up”);
} else {
var uniqueItems = _.orderBy(items, function(x){
return x.Phone;
},[‘asc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort3”, “down”);
}
},

sortByRevenue : function(component) {
var items = component.get(“v.accountItems”);
if(component.get(“v.sort4”) === “down”){
var uniqueItems = _.orderBy(items, function(x){
return x.AnnualRevenue;
},[‘desc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort4”, “up”);
} else {
var uniqueItems = _.orderBy(items, function(x){
return x.AnnualRevenue;
},[‘asc’]);
component.set(“v.accountItems”, uniqueItems);
component.set(“v.sort4”, “down”);
}
},
})

[/sourcecode]

Next step is to add CSS.

sortingCmp.css

[sourcecode language=”css”]
.THIS .MyContent {
padding-left:20px;
padding-top:75px;
width: 90%;
}

.THIS .iconButton{
box-shadow: none;
font-weight: normal;
}

.THIS .iconSVGButton{
fill: white;
}
[/sourcecode]

In the last step component is called from the Lightning application.

sortingApp.app

[sourcecode language=”html”]

<aura:application >
<c:sortingCmp />
</aura:application>

[/sourcecode]

In the Preview click on the column buttons to get the sorted lists.

screen-shot-2016-09-07-at-11-30-44-am

To remove duplicates:

Scenario 1: Let us take the same example as above displaying the list of objects. Now say it has duplicates as shown in the below image and we want to remove this duplicates. Instead of iterating with for loops and if conditions we can use Lodash to get the expected results.

screen-shot-2016-09-07-at-8-30-39-pm

Use the below code in the JavaScript controller to remove the duplicates.

removeDuplicates.js

[sourcecode language=”javascript”]
removeDuplicates: function(component) {
var items = component.get(“v.accountItems”);
var uniqueItems = _.uniqWith(items, _.isEqual);
component.set(“v.accountItems”, uniqueItems);
},
[/sourcecode]

Scenario 2: Suppose we have objects with one particular field being same, say name field and we want this field to be unique.

screen-shot-2016-09-07-at-8-20-52-pm

To remove the object with duplicate names use the below code.

removeDupsByField.js

[sourcecode language=”javascript”]
removeDupsByField: function(component) {
var items = component.get(“v.accountItems”);
var uniqueItems = _.uniqBy(items, function(temp) {
return temp.Name;
});
component.set(“v.accountItems”, uniqueItems);
},
[/sourcecode]

The method which we used for removing duplicates keeps the first occurrence of the element and removes the other. In this example we will have object with city Austin kept and object with city Burlington removed. If you want the opposite to happen i.e. Burlington kept and Austin removed, first we have to reverse the array and use the remove duplicate method. Following is the code for reversing an array.

reverseElements.js

[sourcecode language=”javascript”]
reverseElements: function(component) {
var items = component.get(“v.accountItems”);
var reverseItems = _.reverse(items);
component.set(“v.accountItems”, reverseItems);
}
[/sourcecode]

Finding particular object in an array of objects:

Scenario 1: We have B which is a single object and A which is list of objects. To find at which index B is located in list of objects A we can use Lodash.

screen-shot-2016-09-08-at-6-58-54-pm

findOneObject.js

[sourcecode language=”javascript”]
findOneObject: function(component) {
var listA = component.get(“v.accountItems”);
var objB = _.find(listA, function(temp) {
if (temp.Name === “Express Logistics and Transport”) {
return temp;
}
});
if (objB !== undefined) {
var index = _.indexOf(listA, objB);
console.log(“Index of element: “+index);
}
},
[/sourcecode]

Scenario 2: We have two list of objects A, B and say B is subset of A. I want to find where the elements of B are located in A. We can find the indexes of elements of B located in A using below code

screen-shot-2016-09-08-at-6-54-26-pm

findObjectsIndex.js

[sourcecode language=”javascript”]
findObjects: function(component) {
var listA = component.get(“v.accountItems”);
var listB = component.get(“v.BItems”);
for (var j = 0; j < listB.length; j++) {
var obj = _.find(listA, function(temp) {
if (temp.Name === (listB[j]).Name) {
return temp;
}
});
if (obj !== undefined) {
var index = _.indexOf(listA, obj);
console.log(“Index of element: “+index);
}
}
},
[/sourcecode]

Similarly we have many other functions in Lodash which can be useful. Other important thing is Lodash works even when Salesforce Locker Service is enabled. This article shows only few methods of Lodash and according to our requirement we can use other methods, implementing them is as similar as the methods shown here.

Related links:

Lodash Documentation

View complete code on Sorting in GitHub

2 thoughts on “Implementing Lodash in Salesforce”

  1. Hi, I need help in lodash, i am not resolving my issue. I add lodash in aura component but give me error like reverse is not defined. Please Help.

Leave a Comment

Your email address will not be published. Required fields are marked *

Recent Posts

salesforce world tour essentials dubai
Salesforce World Tour Essentials Dubai | May 16, 2024
simplifying npl the magic of natural language processing
Simplifying NLP: The Magic of Natural Language Processing
streamlining-salesforce deployment with gearset a devops revolution Part 2
Streamlining Salesforce Deployment with Gearset: A DevOps Revolution (Part 2)
streamlining-salesforce deployment with gearset a devops revolution Part 1
Streamlining Salesforce Deployment with Gearset: A DevOps Revolution (Part1)
apache ant with provar automation tool
Apache Ant With Provar Automation Tool
Scroll to Top