Switching to Salesforce Lightning: The Case of JavaScript Promises and Lightning Experience

Switching to Salesforce Lightning

Explore how Lightning Salesforce can assist business users through the benefits of Lightning Experience and the code simplifications brought by JavaScript Promises

Technological innovation often results in the simplification of processes, which makes them more efficient. In such a context, Salesforce Lightning is exactly what business users, who do not have programming experience, want. Why? Here, we would like to answer that question by presenting a case of two Salesforce Lightning components, namely Salesforce Lightning Experience and Salesforce Lightning Promises. Building a case in favor of Salesforce Lightning, we will explore the key benefits of switching to Salesforce Experience, illustrate how building employee or customer lists can be achieved through Lightning Promises, and present several success stories of companies that switched to the Lightning framework

Salesforce Lightning Experience and Salesforce Lightning Promises in a nutshell.

And, what is Salesforce Lightning in in the first place? Salesforce Lightning is a specific component-based structure used in app development. Salesforce designed it to help simplify various processes for clients who do not have sufficient programming experience. The platform achieves its effectiveness through different instruments, including Lightning Experience and Lightning Promises. 

What is the Salesforce Lightning Experience? The Lightning Experience is uniquely-designed pages within the Salesforce framework. They are optimized for boosting sales and customer service. The answer is in the name itself. Lightning Experience offers features that help to improve the customer experience. Additionally, users benefit from interactive and flexible tools that are designed to assist them in visualizing data, thus they make better customer-based decisions.

What is Salesforce Lightning Promise? Salesforce Lightning generally helps with app development. In a narrower approach, Lightning Experience helps with customer service. In turn, Lightning Promises provides an even narrower aspect to the overall Salesforce platform. Promises simplifies code which then allows different operations to be coupled together. Promises often works with getting data and then operating on that data through the Apex platform. In other words, Lightning Promises simplifies the developer’s job as they work with data components. 

Benefits of switching to Salesforce Lightning Experience

As it was mentioned, the Salesforce Lightning platform includes Lightning Experience, which is a modern interface that helps your business operate faster and smarter. In addition, users can benefit from:

  • A customizable homepage with a balanced page layout. It improves the user’s experience by presenting information and the work needed from a login on a well-tailored user interface.
  • Enlarged dashboards. The platform has dashboards with more than three columns for greater accessibility to information.
  • A smart dynamic view featuring improved analytics. The feature ensures retention of the ideas that users access. 

These are foundational advantages that Salesforce Lighting Experience offers in comparison to platforms like Visualforce. 

Using Salesforce Lightning Promises

App developers are often challenged with handling frameworks directed at creating viable employee and customer lists that help optimize the company’s workflow. In such cases, Lightning Promises or Lightning software can be a massive help.  Since Winter 17, ES6 Promises (also known as JavaScript Promises) can be used in Lightning Controllers and Helpers. They help chain asynchronous server-side requests and process them in ES6 synchronous style coding. Salesforce documentation does not reveal much about it, but gives some basic examples. When implementing Promises in Lightning, there are several key aspects to consider.

Lightning datatable

Lightning datatable may be helpful in displaying table data within Lightning if there is no need for custom checkbox columns or customizable hints. Datatable has been available since the Winter ’18 Salesforce release. It helps to display tabular data which has been formatted according to type. For example, emails or phones are shown as links that open a mail or phone client if the class is configured correctly. The standard component inherits styles from the Lightning Design System.

Other interesting features are sorting and infinite scrolling. However, you need some custom code to implement them. Building some simple custom components on top of the standard ones makes sense as it would display all the interesting features and simultaneously be flexible enough to adapt to different cases without much code modification. To present JavaScript Promises without getting too much into complex details, the key focus is on sorting thus avoiding infinite scrolling.

Use-case data model

Now, let’s build a custom employee list application in Lightning using datatable. The table view will display: First Name, Last Name, Date of Birth, Hire Date, Branch/Department, Position, Email, and the Employee’s phone number.Employee list

At this point, you can use the standard Contact object as a source of data and create a separate Employee record type to distinguish employee data from other Contact types in the Salesforce organization.

Mock-data generation framework

In order to demonstrate, it is crucial to get some mock data. Salesforce itself generates mock data in the new developer edition organization registration. Sometimes, ETL tools or automation scripts are used to populate simulated data. However, instead of using some additional software to prepare the demonstration data, it is possible to write some simple native Apex code.

The following screenshot uses a custom Apex generation framework with the subsequent generation string to create mock data. 

Contact: RecordTypeId=r.Employee, 
FirstName=rvs.firstNames, LastName=rvs.lastNames, BirthDate=random.date,
HireDate__c=random.date, Branch__c=random.picklist, Position__c=random.picklist,
Phone=random.ukrainian.cell.phone, Email=builder.FirstName[0]+LastName+@gmail.com

The generation framework creates random Contact data with an Employee record type. It randomly takes FirstName and LastName from a predefined data bank and sets the Birth Date and Hire Date to random date values. Also, it sets Branch and Position to random values found in a picklist and sets phones to random cell numbers, which follow local cell phone number patterns. The first letter from FirstName is taken and concatenated to LastName, and then a string literal to populate the email values.

Datatable apex controller code snippet

To implement this app, we need first to implement the Simple Data Table component and its Apex Controller. Let’s start with the Apex Controller.

/**
 * Created by Bohdan Dovhan on 1/26/2018.
 */
public with sharing class SimpleDataTableController {
    
    @AuraEnabled
    public static Map<String, Object> getColumnsAndData(
            String sObjectName, List<String> sObjectFieldsNames, String whereClause
    ) {
        try{
            Map<String, Schema.SObjectField> m = Schema.describeSObjects(sObjectName.split(','))[0].fields.getMap();
            List<Object> columns = new List<Object>();
            for ( String fieldName: sObjectFieldsNames ) {
                Schema.DescribeFieldResult dfr = m.get( fieldName ).getDescribe();
                Map<String, Object> column = new Map<String, Object>{
                    'label' => dfr.getLabel(),
                    'fieldName' => dfr.getName(),
                    'type' => String.valueOf( dfr.getType() ).toLowerCase(),
                    'sortable'=>true
                };
                columns.add( column );
            }
            String query = 'SELECT ' + String.join( sObjectFieldsNames, ', ') + ' FROM ' + sObjectName;
            if (!String.isBlank(whereClause)) {
                query += ' WHERE ' + whereClause;
            }
            
            List<SObject> records = Database.query( query );
            return new Map<String, Object>{
                'columns' => columns,
                'data' => records
            };
        } catch(Exception e) {
            throw AuraUtils.buildAuraHandledException(e);
        }
    }
}

This class has one static aura enabled by the getColumnsAndData method, which returns columns and data as values of two properties of a common map. It takes three parameters. The Object name will be Contact for the given use case. The Fields names list will contain the fields we mentioned before in the data model section. A clause parameter would restrict the results only to data having an Employee record type.

The code automatically prepares the data and column parameters that are required for the standard Lightning DataTable component. Also, if an exception happens, it is converted to AuraHandledException which the Lightning framework can gracefully display.

Datatable lighting component code snippet

Now let’s build the SimpleDataTable Lightning component.

<aura:component controller="SimpleDataTableController">
	<aura:attribute name="sObjectName" type="String" description="Input attribute to define which sObject to use" required="true"/>
    <aura:attribute name="sObjectFieldsNames" type="List" description="Input attribute to define which sObject fields to use" required="true"/>
	<aura:attribute name="whereClause" type="String" description="Input attribute to define where clause" required="false"/>
    <aura:attribute name="data" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    <lightning:datatable data="{! v.data }" columns="{! v.columns }" keyField="id" hideCheckboxColumn="true" onsort="{!c.updateColumnSorting}"/>                
</aura:component>

You can build a Lightning Javascript controller for this component. This component is based on the standard DataTable element. Still, it prepares the required data so that the developer does not need to pass the data or columns here, but rather specifies only the name of SObject, fields list, and the clause where the required data can be found. Sorting is also enabled here.

 ({
	init : function(component, event, helper) {
	    helper.callActionAsPromise(
	        component,
	        helper,
	        'c.getColumnsAndData',
	        {
	            'sObjectName': component.get('v.sObjectName'),
	            'sObjectFieldsNames': component.get('v.sObjectFieldsNames'),
	            'whereClause': component.get('v.whereClause')
	        }
	    ).then(function(r) {
	        component.set('v.columns', r.r.columns);
	        component.set('v.data', r.r.data);
	    })
	},
    
    // Client-side controller called by the onsort event handler
    updateColumnSorting: function (cmp, event, helper) {
        var fieldName = event.getParam('fieldName');
        var sortDirection = event.getParam('sortDirection');
        // assign the latest attribute with the sorted column fieldName and sorted direction
        event.getSource().set("v.sortedBy", fieldName);
        
        event.getSource().set("v.sortedDirection", sortDirection);
        helper.sortData(cmp, fieldName, sortDirection);
    }
})

On init apex controller, getColumnsAndData is called as a promise. This allows the code to look synchronous by calling the method. updateColumnSorting calls on another helper method to perform sorting on the client-side. 

Let’s discuss the Salesforce Lightning Javascript Helper code next.

({
	callActionAsPromise : function(component, helper, actionName, params) {
        return new Promise($A.getCallback(function(resolve, reject) {
            let action = component.get(actionName);
            action.setParams(params);
            action.setCallback(helper, function(actionResult) {
                if (actionResult.getState() === 'SUCCESS') {
                    resolve({'c':component, 'h':helper, 'r':actionResult.getReturnValue()});
                } else {
                    let errors = actionResult.getError();
                    reject(new Error(errors && Array.isArray(errors) && errors.length === 1 ? errors[0].message : JSON.stringify(errors)));
                }
            });
            $A.enqueueAction(action);
        }));
    },
    
    sortData: function (cmp, fieldName, sortDirection) {
        var data = cmp.get("v.data");
        var reverse = sortDirection !== 'asc';
        //sorts the rows based on the column header that's clicked
        data.sort(this.sortBy(fieldName, reverse))
        cmp.set("v.data", data);
    },
    sortBy: function (field, reverse, primer) {
        var key = primer ?
            function(x) {return primer(x[field])} :
            function(x) {return x[field]};
        //checks if the two rows should switch places
        reverse = !reverse ? 1 : -1;
        return function (a, b) {
            return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
        }
    }
})

The first method, callActionAsPromise, can be moved to some basic abstract component for a complex project and then reused to call any apex server-side action as a promise. It checks the action result state and resolves it if the condition is successful or it otherwise rejects it. 

The sorting methods sortData and sortBy completely coincide with the documentation sample methods. Only the Javascript controller method for sorting was changed. One should note that samples from Salesforce documentation do not always work out of the box and sometimes they require slight changes to make them work properly.

Employee list and app code snippet

Now, you can move on to the final component code snippet. What strikes the most –  it looks readable.

<aura:component >
	<c:SimpleDataTable sObjectName="Contact"
                 sObjectFieldsNames="FirstName,LastName,BirthDate,HireDate__c,Branch__c,Position__c,Email,Phone"
                 whereClause="RecordType.Name = 'Employee'"
    />
</aura:component>

And, so does the application code.

<aura:application extends="force.slds">
    <c:SimpleEmployeeList />
</aura:application>

The Lightning SimpleEmployeeListApp standalone application consists of one SimpleEmployeeList component. It refers to the SimpleDataTable component, which sets sObjectName as Contact, and  fields to a predefined list of areas. It also populates where a clause restricts data results to only employee data. Now, you can click and sort by the first name column.Employee list fields

Notice that data is sorted by FirstName sorts data in ascending order. Also, you can click on the email links to launch the default email application and click on the phone links to prompt for phone link application launch. By clicking again on the FirstName column, you will get the data sorted in descending order.FirstName column

This process required neither a custom checkbox column nor a custom radio button column in the considered use case. The system also did not depend on other requirements that the standard Lightning datatable component may not support. For complicated use cases, more custom code might be needed or alternative open source components might be used, which will support the requirements for such use cases.

Real-life successes of switching to Salesforce Lightning

The following are actual success stories that illustrate how switching to Salesforce Lightning is a major advantage in terms of optimizing and enhancing various management processes.

From VisualForce to Salesforce Lightning From VisualForce to Salesforce Lightning

The case below illustrates how within 3 weeks the multi-package management system was transferred from VisualForce to Salesforce Lightning. The Client, a leading Pharma and Clinical research company, approached us with a pressing need to transfer their existing CRM systems from Salesforce Classic UI to Lightning UI. Within an extremely tight timeframe, the Client expected our team of Salesforce specialists to transfer all their custom VisualForce pages to Lightning and to implement some new components in Lightning. Migrating Visualforce pages was scheduled to be performed within the short deadlines.

The Salesforce Lightning development team successfully converted the system to a consistent developer and end-user Salesforce Lightning solution. Utilizing key elements like enhanced dashboards, customized paths, performance charts, and task prioritization, the team built an actionable Salesforce Lightning solution that sped up internal and external interoperability and decision-making within sales, clinical trials, operations, and general management. Essentially, this example shows how Salesforce Lightning solutions are applicable to a wide range of customer-related operations.

Managing customers more effectively with Salesforce Lightning 

The case presented further portrays the provision of a smooth integration between Lightning and mobile native features. The Client needed connectivity between Salesforce Lightning responsive pages and mobile native features, including contact lists (the ones discussed earlier, and sales workflows, in order to allow globally positioned sales representatives to manage their customers more efficiently.

By using Salesforce Lightning, Salesforce developers provided a responsive application that leverages the HTML 5/AJAX user experience offered by the Lightning Component framework. This was wrapped with a Native App and a native features connector to provide access to a phone/tablets contact list. The solution dramatically increased the effectiveness of sales representatives and the Salesforce technology adoption by removing the necessity to manage contact lists directly in Salesforce. In addition, Lightning Components offered a responsive user experience off the shelf and added the ability to leverage connectivity to native features.  Such a degree of connectivity allows tight integration of apps with operating systems and hardware; e.g., access to contacts, mail, maps, search, and hardware elements, including the camera, microphone, etc.

Wrapping up

Switching to Salesforce Lightning offers access to components like Lightning Experience and Lightning Promises. Essentially, as we’ve discussed, these features help create better management systems, as well as to help simplify the coding process in app development. Salesforce Lightning can be of great service in optimizing employee lists and improving a customer’s experience.

If you have any questions, ask us here

Want to know how to migrate from Salesforce Classic to Salesforce Lightning? Proceed here.

Don’t know how to choose the right Salesforce partner for your company? Click here.

Back to overview