Tag Archives: Lightning

How to use jQuery in Salesforce Lightning Aura Component?

Step 1: Upload the jQuery library as a static resource in your Org.

Step 2: Use ltng:require to load static resource JavaScript libraries on your component.

<aura:component>
    <ltng:require scripts="{!$Resource.YourStaticResourceName + '/jQueryFileName.js'}" />
</aura:component>

Step 3: To utilize the library include the afterScriptsLoaded event and add the method in your aura component JS controller.

Aura Component :

<aura:component>
    <ltng:require scripts="{!$Resource.YourStaticResourceName + '/jQueryFileName.js'}" afterScriptsLoaded="{!c.handleAfterScriptsLoaded}" />
</aura:component>

JS Controller:

({
    handleAfterScriptsLoaded : function(component, event, helper) {
        jQuery("document").ready(function(){
            console.log('jQuery Loaded');
        });
    }
})

Generic File Related List Lightning Component

Apex Class:

/*
@Author : Biswajeet Samal
@CreatedDate : 08th Aug 2020
@Description : Related Files Controller
*/
public class RelatedFilesController {
    
    @AuraEnabled
    public static List<ContentDocument> getRelatedDocs(Id recordId){
        List<ContentDocument> cdList = new List<ContentDocument>();
        List<ContentDocumentLink> cdlList = [SELECT ContentDocumentId FROM ContentDocumentLink
                                             WHERE LinkedEntityId = :recordId];
        Set<Id> cdIds = new Set<Id>();
        for (ContentDocumentLink cdl : cdlList) {
            cdIds.add(cdl.ContentDocumentId); 
        }        
        cdList = [SELECT Id, Title, FileType, OwnerId, Owner.Name, CreatedDate,
                  CreatedById, CreatedBy.Name, ContentSize
                  FROM ContentDocument WHERE Id IN :cdIds];
        return cdList;
    }
    
    @AuraEnabled
    public static string getDocURL(Id docId){
        ContentVersion cv = [SELECT Id FROM ContentVersion WHERE ContentDocumentId = :docId AND IsLatest = true];
        String cvDownloadURL = URL.getSalesforceBaseUrl().toExternalForm() + '/sfc/servlet.shepherd/version/download/' + cv.Id;
        return cvDownloadURL;
    }
    
    @AuraEnabled
    public static void deleteDoc(Id docId){
        ContentDocument conDoc = new ContentDocument(Id = docId);
        delete conDoc;
    }
}

Lightning Component:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" controller="RelatedFilesController">
    
    <!--Attributes-->
    <aura:attribute name="cdList" type="List"/>
    
    <!--Handlers--> 
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <!--Component Start-->
    <table class="slds-table slds-table_cell-buffer slds-table_bordered">
        <thead>
            <tr class="slds-line-height_reset">
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Title">Title</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="File Type">File Type</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Created By">Created By</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Created Date">Created Date</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    
                </th>
            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.cdList}" var="cd">
                <tr>
                    <th scope="row">
                        <div class="slds-truncate" title="{!cd.Title}">
                            <a onclick="{!c.handleSelectedDocPreview}" data-Id="{!cd.Id}">{!cd.Title}</a>
                        </div>
                    </th>
                    <th scope="row">
                        <div class="slds-truncate" title="{!cd.FileType}">
                            {!cd.FileType}
                        </div>
                    </th>
                    <th scope="row">
                        <div class="slds-truncate" title="{!cd.CreatedBy.Name}">
                            <a onclick="{!c.handleRedirectToUserRecord}" data-Id="{!cd.CreatedById}">{!cd.CreatedBy.Name}</a>
                        </div>
                    </th>
                    <th scope="row">
                        <div class="slds-truncate" title="{!cd.CreatedDate}">
                            <lightning:formattedDateTime value="{!cd.CreatedDate}"/>
                        </div>
                    </th>
                    <th scope="row">
                        <lightning:buttonMenu alternativeText="Show menu" menuAlignment="auto" onselect="{!c.handleSelectedAction}" value="{!cd.Id}">
                            <lightning:menuItem value="Download" label="Download" iconName="utility:download" title="Download" />
                            <lightning:menuItem value="Delete" label="Delete" iconName="utility:delete" title="Delete"/>
                        </lightning:buttonMenu>
                    </th>
                </tr>  
            </aura:iteration>
        </tbody>
    </table>
    <!--Component End-->
</aura:component>

Lightning Component JS Controller:

({
    //Get Related Docs
    doInit : function(component, event, helper) {
        helper.getRelatedDocuments(component, event); 
    },
    
    //Redirect To User Record
    handleRedirectToUserRecord: function (component, event, helper) {
        var recordId = event.currentTarget.getAttribute("data-Id")
        var navEvt = $A.get("e.force:navigateToSObject");
        navEvt.setParams({
            "recordId": recordId,
            "slideDevName": "Detail"
        });
        navEvt.fire();
    },
    
    //Preview Selected File
    handleSelectedDocPreview : function(component,event,helper){ 
        $A.get('e.lightning:openFiles').fire({
            recordIds: [event.currentTarget.getAttribute("data-Id")]
        });
    },
    
    //Handle Selected Action
    handleSelectedAction: function(component, event, helper) {
        var docId = event.getSource().get("v.value");
        var selectedMenuValue = event.detail.menuItem.get("v.value");
        switch(selectedMenuValue) {
            case "Delete":
                helper.deleteDocument(component, event, docId);
                break;
            case "Download":
                helper.downloadDocument(component, event, docId);
                break;
        }
    }
})

Lightning Component JS Helper:

({
    getRelatedDocuments : function(component, event) {
        var action = component.get("c.getRelatedDocs");
        action.setParams({
            recordId : component.get("v.recordId")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS"){
                component.set('v.cdList', response.getReturnValue());
            }else if(state === "INCOMPLETE") {
                console.log("INCOMPLETE");
            }else if(state === "ERROR"){
                var errors = response.getError();
                if(errors){
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " +  errors[0].message);
                    }
                }else{
                    console.log("Unknown error");
                }
            }
        });
        $A.enqueueAction(action);  
    },
    
    deleteDocument : function(component, event, docId) {
        var action = component.get("c.deleteDoc");
        action.setParams({
            docId : docId
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS"){
                this.getRelatedDocuments(component, event);
            }else if(state === "INCOMPLETE") {
                console.log("INCOMPLETE");
            }else if(state === "ERROR"){
                var errors = response.getError();
                if(errors){
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " +  errors[0].message);
                    }
                }else{
                    console.log("Unknown error");
                }
            }
        });
        $A.enqueueAction(action);  
    },
    
    downloadDocument : function(component, event, docId) {
        var action = component.get("c.getDocURL");
        action.setParams({
            docId : docId
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS"){
                var urlEvent = $A.get("e.force:navigateToURL");
                urlEvent.setParams({
                    "url": response.getReturnValue()
                });
                urlEvent.fire();
            }else if(state === "INCOMPLETE") {
                console.log("INCOMPLETE");
            }else if(state === "ERROR"){
                var errors = response.getError();
                if(errors){
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " +  errors[0].message);
                    }
                }else{
                    console.log("Unknown error");
                }
            }
        });
        $A.enqueueAction(action);  
    }
})

Salesforce Lightning URL Hacking

Here I have created a custom detail button(New Contact) on Account object with some pre-populated Contact field values from Account record using Lightning URL Hacking.

Go to setup | Object Manager | Account | Buttons, Links, and Actions | Create a new Button

  • Label – New Contact
  • Display Type – Detail Page Button
  • Behavior – Display in new window
  • Content Source – URL

URL Content:

/lightning/o/Contact/new?defaultFieldValues= OwnerId={!Account.OwnerId},AccountId={!Account.Id},MailingStreet={!Account.ShippingStreet},MailingCity={!Account.ShippingCity},MailingState={!Account.ShippingState},MailingPostalCode={!Account.ShippingPostalCode},MailingCountry={!Account.ShippingCountry}

Add this button to Account detail page layout, “Mobile & Lightning Action” section.

Note: This URL Hacking with button doesn’t work in Salesforce1 mobile app.

Lightning Custom Datatable With Pagination

Apex Class:

public class AccountController {
    
    @AuraEnabled//Get Account Records
    public static List<Account> getAccountList(Integer pageSize, Integer pageNumber){
        List<Account> accList = new List<Account>();
        ApexPages.StandardSetController ssc = new ApexPages.StandardSetController(Database.getQueryLocator('SELECT Id, Name, AccountNumber, Industry, Phone FROM Account'));
        ssc.setpagesize(pageSize);
        ssc.setPageNumber(pageNumber);
        accList = (List<Account>)ssc.getRecords();
        return accList;
    }
}

Lightning Component:

<aura:component implements="flexipage:availableForAllPageTypes,force:appHostable" controller="AccountController">
    
    <!--Declare Attributes-->
    <aura:attribute name="accList" type="Account[]"/>
    <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"/>
    <!--Declare Handler-->
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <!--Component Start-->
    <div class="slds-m-around--xxx-large">               
        
        <lightning:card>
            <aura:set attribute="title">
                Account
            </aura:set>
            <aura:set attribute="footer">
                <div class="slds-align_absolute-center"> 
                    <div class="slds-p-right_xx-small">
                        <lightning:button label="Prev"
                                          onclick="{!c.handlePrev}"
                                          disabled="{! v.pageNumber == 1}"
                                          variant="brand"
                                          iconName="utility:back"
                                          name="prev"/>
                    </div>
                    <span class="slds-badge slds-badge_lightest">
                        Page {!v.pageNumber} | Showing records from {! ((v.pageNumber-1)*v.pageSize)+' to '+((v.pageNumber-1)*v.pageSize+v.dataSize)}
                    </span>
                    <div class="slds-p-left_xx-small">
                        <lightning:button label="Next"
                                          disabled="{!v.isLastPage}"
                                          onclick="{!c.handleNext}" 
                                          variant="brand"
                                          iconName="utility:forward"
                                          iconPosition="right"
                                          name="next"/>
                    </div>
                </div>  
                
            </aura:set>
            <table class="slds-table slds-table_cell-buffer slds-table_bordered">
                <thead>
                    <tr class="slds-line-height_reset slds-text-title_caps">
                        <th  class="slds-is-resizable" scope="col">
                            <div class="slds-truncate" title="Name">
                                Name
                            </div>
                        </th>
                        <th  class="slds-is-resizable" scope="col">
                            <div class="slds-truncate" title="Account Number">
                                Account Number
                            </div>
                        </th>
                        <th class="slds-is-resizable" scope="col">
                            <div class="slds-truncate" title="Industry">
                                Industry
                            </div>
                        </th>
                        <th class="slds-is-resizable" scope="col">
                            <div class="slds-truncate" title="Phone">
                                Phone
                            </div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Actions">Actions</div>
                        </th>
                    </tr>
                </thead>
                <aura:if isTrue="{!v.accList.length > 0}">
                    <tbody>
                        <aura:iteration items="{!v.accList}" var="acc">
                            <tr class="slds-hint-parent">
                                
                                <th data-label="Name" scope="row">
                                    <div class="slds-truncate" title="{!acc.Name}">
                                        {!acc.Name}
                                    </div>
                                </th>
                                <td data-label="Account Number">
                                    <div class="slds-truncate" title="{!acc.AccountNumber}">{!acc.AccountNumber}</div>
                                </td>
                                <td data-label="Industry">
                                    <div class="slds-truncate" title="{!acc.Industry}">{!acc.Industry}</div>
                                </td>
                                <td data-label="Phone">
                                    <div class="slds-truncate" title="{!acc.Phone}">{!acc.Phone}</div>
                                </td>
                                <td data-label="Action">
                                    <lightning:buttonIcon name="{!acc.Id}" iconName="utility:delete" title="Delete" variant="bare" onclick="{!c.handleDeleteAccount}" alternativeText="Delete" />                                                                            
                                </td>
                                
                            </tr>
                        </aura:iteration>
                    </tbody>
                </aura:if>
            </table>
            <aura:if isTrue="{!empty(v.accList)}">
                <div class="slds-align_absolute-center">
                    No records found
                </div>
            </aura:if>
        </lightning:card>
    </div>
    <!--Component End-->
</aura:component>

Lightning JS Controller :

({
    doInit : function(component, event, helper) {        
        helper.getAccounts(component, event);
    },
    
    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);
    },
    
    handleDeleteAccount: function (component, event, helper) {
        alert('Selected Account to delete - ' + event.getSource().get("v.name"));
    },
})

Lightning JS Helper:

({
    getAccounts : function(component, event) {
        var action = component.get("c.getAccountList");
        action.setParams({
            'pageSize' : component.get("v.pageSize"),
            'pageNumber' : component.get("v.pageNumber")
        });
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var result = response.getReturnValue();
                if(result.length < component.get("v.pageSize") || result.length == 0){
                    component.set("v.isLastPage", true);
                } else{
                    component.set("v.isLastPage", false);
                }
                component.set("v.dataSize", result.length);
                component.set("v.accList", result);
            }
        });
        $A.enqueueAction(action);
    },
})

Return Custom Error Messages From Apex Controller In Salesforce Lightning

Sample Code:

We can use System.AuraHandledException to return custom error message from server side apex controller to lightning component in Salesforce.

string errorMessage = 'Your Error Message';
AuraHandledException auraEx = new AuraHandledException(errorMessage);
auraEx.setMessage(errorMessage);
throw auraEx;