Category Archives: Salesforce

Salesforce Lightning Datatable With Pagination

Apex Class:

public class SampleController {
    
    //Get Account Records
    @AuraEnabled
    public static  List<Account> getAccounts(Integer pageSize, Integer pageNumber){
        Integer offset = (pageNumber - 1) * pageSize;
        List<Account> accList = new List<Account>();
        accList = [SELECT Id, Name, AccountNumber, Industry, Phone FROM Account LIMIT :pageSize OFFSET :offset];
        return accList;
    }
    
    //Delete Account
    @AuraEnabled
    public static void deleteAccount(Account acc){
        Delete acc;
    } 
}

Lightning Component:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" controller="SampleController">
    
    <aura:attribute name="data" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    <aura:attribute name="pageNumber" type="Integer" default="1"/>
    <aura:attribute name="pageSize" type="Integer" default="10"/>
    <aura:attribute name="isLastPage" type="Boolean" default="false"/>
    <aura:attribute name="dataSize" type="Integer" default="0"/> 
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <div class="slds-m-around_xx-large">
        <div class="slds-clearfix">
            <div class="slds-page-header" role="banner">
                <p class="slds-page-header__title">Accounts</p>
            </div>
        </div>
        
        <lightning:datatable aura:id = "accDT"
                             columns = "{!v.columns}"
                             maxRowSelection="{!v.maxRowSelection}"
                             data = "{!v.data}"
                             keyField = "Id"
                             selectedRows = "{!v.selectedRowList}"
                             onrowaction="{!c.handleRowAction}"/>
        
        <div class="slds-clearfix">
            <div class="slds-page-header" role="banner">
                <div class="slds-float_right">            
                    <lightning:button label="Prev" iconName="utility:chevronleft" iconPosition="left"
                                      onclick="{!c.handlePrev}" disabled="{! v.pageNumber == 1}"/>
                    <lightning:button label="Next" iconName="utility:chevronright" iconPosition="right" 
                                      disabled="{! v.isLastPage}" onclick="{!c.handleNext}"/>
                </div>
                <p class="slds-page-header__title">Page {!v.pageNumber} | Showing records from {! ((v.pageNumber-1)*v.pageSize)+' to '+((v.pageNumber-1)*v.pageSize+v.dataSize)}</p>
            </div>
        </div>
    </div>
</aura:component>

Lightning JS Controller:

({
    doInit : function(component, event, helper) {        
        helper.getColumnAndAction(component);
        helper.getAccounts(component, helper);
    },
    
    handleNext : function(component, event, helper) { 
        var pageNumber = component.get("v.pageNumber");
        component.set("v.pageNumber", pageNumber+1);
        helper.getAccounts(component, helper);
    },
    
    handlePrev : function(component, event, helper) {        
        var pageNumber = component.get("v.pageNumber");
        component.set("v.pageNumber", pageNumber-1);
        helper.getAccounts(component, helper);
    },

    handleRowAction: function (component, event, helper) {
        var action = event.getParam('action');
        switch (action.name) {
            case 'edit':
                helper.editRecord(component, event);
                break;
            case 'delete':
                helper.deleteRecord(component, event);
                break;
            case 'view':
                helper.viewRecord(component, event);
                break;
        }
    },
})

Lightning JS Helper:

({
    getColumnAndAction : function(component) {
        var actions = [
            {label: 'Edit', name: 'edit'},
            {label: 'Delete', name: 'delete'},
            {label: 'View', name: 'view'}
        ];
        component.set('v.columns', [
            {label: 'Name', fieldName: 'Name', type: 'text'},
            {label: 'AccountNumber', fieldName: 'AccountNumber', type: 'text'},
            {label: 'Industry', fieldName: 'Industry', type: 'text'},
            {label: 'Phone', fieldName: 'Phone', type: 'phone'},
            {type: 'action', typeAttributes: { rowActions: actions } } 
        ]);
    },
    
    getAccounts : function(component, helper) {
        var action = component.get("c.getAccounts");
        var pageSize = component.get("v.pageSize").toString();
        var pageNumber = component.get("v.pageNumber").toString();
        
        action.setParams({
            'pageSize' : pageSize,
            'pageNumber' : pageNumber
        });
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var resultData = response.getReturnValue();
                if(resultData.length < component.get("v.pageSize")){
                    component.set("v.isLastPage", true);
                } else{
                    component.set("v.isLastPage", false);
                }
                component.set("v.dataSize", resultData.length);
                component.set("v.data", resultData);
            }
        });
        $A.enqueueAction(action);
    },
    
    viewRecord : function(component, event) {
        var row = event.getParam('row');
        var recordId = row.Id;
        var navEvt = $A.get("event.force:navigateToSObject");
        navEvt.setParams({
            "recordId": recordId,
            "slideDevName": "detail"
        });
        navEvt.fire();
    },
    
    deleteRecord : function(component, event) {
        var action = event.getParam('action');
        var row = event.getParam('row');
        
        var action = component.get("c.deleteAccount");
        action.setParams({
            "acc": row
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS" ) {
                var rows = component.get('v.data');
                var rowIndex = rows.indexOf(row);
                rows.splice(rowIndex, 1);
                component.set('v.data', rows);
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "Success!",
                    "message": "The record has been delete successfully."
                });
                toastEvent.fire();
            }
        });
        $A.enqueueAction(action);
    },
    
    editRecord : function(component, event) {
        var row = event.getParam('row');
        var recordId = row.Id;
        var editRecordEvent = $A.get("e.force:editRecord");
        editRecordEvent.setParams({
            "recordId": recordId
        });
        editRecordEvent.fire();
    },    
})

Output:

Salesforce Apex Switch Statement

From Summer ’18 Release Apex now supports switch statement, that tests whether an expression matches one of several values and branches accordingly.

Syntax:

switch on expression {
    when value1 {		// when block 1
        // code block 1
    }	
    when value2 {		// when block 2
        // code block 2
    }
    when value3 {		// when block 3
        // code block 3
    }
    when else {		  // when else block, optional
        // code block 4
    }
}

Example:

for(Integer i=1; i<=5; i++){
    Switch on i {
        when 1,2{
            System.debug('case 1 and 2');
        }
        when 5{
            System.debug('case 5');
        }
        when else{
            System.debug('case 3 and 4');
        }
    }
 }

The switch statement evaluates the expression and executes the code block for the matching when value. If no value matches, the code block for the when else block is executed. If there isn’t a when else block, no action is taken.

Get Picklist Values Dynamically In Lightning Component

In below example I’m retrieving “Account” object “Industry” picklist values and populating on lightning component using lightning:select and creating account record.

Apex Controller:

public class SampleAuraController {
    
    @AuraEnabled //Save Account Data
    Public static void createAccount(Account objacc){
        try{
            //Insert Account Record
            insert objacc; 
            
        }catch(Exception e){
            //throw exception message
            throw new AuraHandledException(e.getMessage());
        }
        finally {
        }
    }
    
    @AuraEnabled //get Account Industry Picklist Values
    public static Map<String, String> getIndustry(){
        Map<String, String> options = new Map<String, String>();
        //get Account Industry Field Describe
        Schema.DescribeFieldResult fieldResult = Account.Industry.getDescribe();
        //get Account Industry Picklist Values
        List<Schema.PicklistEntry> pList = fieldResult.getPicklistValues();
        for (Schema.PicklistEntry p: pList) {
            //Put Picklist Value & Label in Map
            options.put(p.getValue(), p.getLabel());
        }
        return options;
    }
}

Lightning Component:

<!--Sample.cmp--> 
<aura:component controller="SampleAuraController" implements="flexipage:availableForAllPageTypes,force:appHostable">
    
    <!--Declare Attributes-->
    <aura:attribute name="industryMap" type="Map"/>
    <aura:attribute name="acc" type="Account" default="{'sobjectType':'Account', 
                                                       'Name': '',
                                                       'AccountNumber': '',
                                                       'Email': '',
                                                       'Phone': '', 
                                                       'Industry': ''}"/>
    
    <!--Declare Handler-->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>  
    
    <!--Component Start--> 
    <div class="slds-m-around--xx-large">
        <div class="container-fluid">
            <div class="form-group">
                <lightning:input name="accName" type="text" required="true" maxlength="50" label="Account Name" value="{!v.acc.Name}" />
            </div>
            <div class="form-group">
                <lightning:input name="accNumber" type="text" required="true" maxlength="10" label="Account Number" value="{!v.acc.AccountNumber}" />
            </div>
            <div class="form-group">
                <lightning:input name="accEmail" type="email" required="true" maxlength="100" label="Email" value="{!v.acc.Email}" />
            </div>
            <div class="form-group">
                <lightning:input name="accPhone" type="phone" required="true" maxlength="10" label="Phone" value="{!v.acc.Phone}" />
            </div>
            <div class="form-group">
                <lightning:select aura:id="industryPicklist" value="{!v.acc.Industry}" onchange="{!c.handleCompanyOnChange}" name="industryPicklist" label="Industry" required="true">
                    <option value="">--None--</option>
                    <aura:iteration items="{!v.industryMap}" var="ind" indexVar="key">
                        <option text="{!ind.value}" value="{!ind.key}" selected="{!ind.key==v.acc.Industry}" />
                    </aura:iteration>
                </lightning:select>
            </div>
        </div>
        <br/>
        <lightning:button variant="brand" label="Submit" onclick="{!c.handleAccountSave}" />              
    </div>
    <!--Component End-->
</aura:component>

Lightning JS Controller:

({
    //Load Account Industry Picklist
    doInit: function(component, event, helper) {        
        helper.getIndustryPicklist(component, event);
    },
    
    //handle Account Save
    handleAccountSave : function(component, event, helper) {
        helper.saveAccount(component, event);
    },
    
    //handle Industry Picklist Selection
    handleCompanyOnChange : function(component, event, helper) {
        var indutry = component.get("v.acc.Industry");
        alert(indutry);
    }
})

Lightning JS Helper:

({
    //get Industry Picklist Value
    getIndustryPicklist: function(component, event) {
        var action = component.get("c.getIndustry");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var result = response.getReturnValue();
                var industryMap = [];
                for(var key in result){
                    industryMap.push({key: key, value: result[key]});
                }
                component.set("v.industryMap", industryMap);
            }
        });
        $A.enqueueAction(action);
    },
    
    //handle Account Save
    saveAccount : function(component, event) {
        var acc = component.get("v.acc");
        var action = component.get("c.createAccount");
        action.setParams({
            objacc : acc
        });
        action.setCallback(this,function(response){
            var state = response.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:

Lightning OverlayLibrary Modal

In Spring 18 Salesforce has provided lightning:overlayLibrary tag to displays messages via modals and popovers. This component requires API version 41.0 and later. lightning:overlayLibrary is not supported in the lightning application. It’s supported only on salesforce lightning experience Lightning, Console, Communities.

In this example, I’m using below components:

Main Component (Sample.cmp) – Will contain lightning:overlayLibrary tag with aura:id attribute and a lightning:button
Modal Content (OverlayLibraryModal.cmp) – The component responsible for containing all the content to show in the Modal as content.

Sample.cmp:

<!--Sample.cmp--> 
<aura:component  implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome" access="global">
    <!--Declare Attribute-->
    <aura:attribute name="FirstName" type="String"/> 
    <aura:attribute name="LastName" type="String"/> 
    
    <lightning:overlayLibrary aura:id="overlayLib"/>
    
    <!--Component Start-->    
    <div class="slds-m-around--xx-large">
        <lightning:input name="fname" label="First Name" value="{!v.FirstName}" />
        <lightning:input name="lname" label="Last Name" value="{!v.LastName}" />
        <br/>
        <lightning:button variant="brand" label="Show Modal" onclick="{!c.handleShowModal}"/>
    </div>
    <!--Component End-->
</aura:component>

SampleController.js:

({
    handleShowModal: function(component) {
        var fName = component.get("v.FirstName");
        var lName = component.get("v.LastName");
        $A.createComponent("c:OverlayLibraryModal",
                           {
                               "FirstName" : fName,
                               "LastName" : lName
                           },
                           function(content, status) {
                               if (status === "SUCCESS") {
                                   var modalBody = content;
                                   component.find('overlayLib').showCustomModal({
                                       header: "Welcome to Biswajeet Samal's Blog",
                                       body: modalBody, 
                                       showCloseButton: true,
                                       closeCallback: function(ovl) {
                                           console.log('Overlay is closing');
                                       }
                                   }).then(function(overlay){
                                       console.log("Overlay is made");
                                   });
                               }
                           });
    }
})

OverlayLibraryModal.cmp:

<aura:component access="global">
    <!--Declare Attribute-->
    <aura:attribute name="FirstName" type="String"/> 
    <aura:attribute name="LastName" type="String"/> 
    <lightning:overlayLibrary aura:id="overlayLib"/>
    
    <!--Component Start-->  
    <div class="slds-m-around--xx-large">
        <p>{!v.FirstName} &nbsp; {!v.LastName} </p>
        <br/>
        <lightning:button variant="brand" label="Cancel" onclick="{!c.handleCloseModal}"/>
    </div>
    <!--Component End-->
</aura:component>

OverlayLibraryModalController.js:

({
    handleCloseModal: function(component, event, helper) {
        //Close the Modal Window
        component.find("overlayLib").notifyClose();
    }
})

Output:

Set or Modify Field Values in Onsubmit Event of lightning:recordeditform

Sometimes we can have a requirement to add or modify field values in onsubmit event of lightning:recordeditform. In below example, I’m creating “Lead” object record using lightning:recordeditform and in onsubmit event, I’m adding “Description” field value of “Lead” object.

Lightning Component:

<!--Sample.cmp--> 
<aura:component implements="flexipage:availableForAllPageTypes,force:appHostable">
    
    <!--Component--> 
    <div class="slds-m-around--xx-large">
        <lightning:card title="Lead" iconName="standard:lead" class="slds-p-around_medium">
            <lightning:recordEditForm aura:id="leadCreateForm" objectApiName="Lead" onsubmit="{!c.handleOnSubmit}">
                <lightning:messages />
                
                <div class="slds-grid">
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="FirstName"></lightning:inputField>
                    </div>
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="LastName"></lightning:inputField>
                    </div>
                </div>
                
                <div class="slds-grid">
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="Email"></lightning:inputField>
                    </div>
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="Phone"></lightning:inputField>
                    </div>
                </div>
                
                <div class="slds-grid">
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="Company"></lightning:inputField>
                    </div>
                </div>
                
                <lightning:button type="submit" label="Save" variant="brand"/>
            </lightning:recordEditForm>
        </lightning:card>
    </div>
</aura:component>

Lightning JS Controller:

({
    handleOnSubmit : function(component, event, helper) {
        event.preventDefault(); //Prevent default submit
        var eventFields = event.getParam("fields"); //get the fields
        eventFields["Description"] = 'Lead was created from Lightning RecordEditForm'; //Add Description field Value
        component.find('leadCreateForm').submit(eventFields); //Submit Form
    }
})