Salesforce Lightning: Global Search

Today we will have a look at creating a custom global search using Lightning and SOSL. We will use SOSL to query the results from database and show it on the lightning component using the lightning:datatable tag


SOSL is preferred over SOQL in use cases where we want to search for a particular keyword across different objects. The return type of SOSL will be a list of list of sobjects.
 List<List<sObject>> searchResult = [FIND :searchKey
                                            IN ALL FIELDS RETURNING
                                            Account (Id, Name, AccountNumber, Website),
                                            Contact(Id, Name, Email, MobilePhone),
                                            Opportunity(Id, Name, StageName, CloseDate),
                                            Lead(Id, Name, Email, Company)];

Lightning datatable was introduced by Salesforce in Winter 18 release. With lightning datatable, now it has become very easy to implement a table in lightning, You just need to specify the columns and pass in your data to the component and the component will take care of creating the table. The table will also have the sort feature implemented by default.

Below is the code used to implement the global search:
GlobalSearch.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="GlobalSearchController">
 
    <!-- handlers-->
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
 
    <!-- attributes -->
    <aura:attribute name="showSearchResults" type="Boolean" default="false"/>
    <aura:attribute name="searchKey" type="String"/>
    <aura:attribute name="accountList" type="List" default="Account[]"/>
    <aura:attribute name="accountColumns" type="List"/>
    <aura:attribute name="contactList" type="List" default="Contact[]"/>
    <aura:attribute name="contactColumns" type="List"/>
    <aura:attribute name="oppList" type="List" default="Opportunity[]"/>
    <aura:attribute name="oppColumns" type="List"/>
    <aura:attribute name="leadList" type="List" default="Lead[]"/>
    <aura:attribute name="leadColumns" type="List"/>
 
    <lightning:layout multipleRows="true">
        <lightning:layoutItem padding="around-small" size="9">
            <lightning:input name="searchKey" placeholder="Enter search key" value="{!v.searchKey}"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="around-small" size="3">
            <lightning:button variant="brand" label="Search" title="Search" onclick="{!c.search}" class="customButton"/>
        </lightning:layoutItem>
    </lightning:layout>
 
    <aura:if isTrue="{!v.showSearchResults}">
        <lightning:layout multipleRows="true">
            <lightning:layoutItem padding="around-small" size="12">
                Account
                <lightning:datatable keyField="id"
                                     data="{!v.accountList}"
                                     columns="{!v.accountColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
            <lightning:layoutItem padding="around-small" size="12">
                Contact
                <lightning:datatable keyField="id"
                                     data="{!v.contactList}"
                                     columns="{!v.contactColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
            <lightning:layoutItem padding="around-small" size="12">
                Opportunity
                <lightning:datatable keyField="id"
                                     data="{!v.oppList}"
                                     columns="{!v.oppColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
            <lightning:layoutItem padding="around-small" size="12">
                Lead
                <lightning:datatable keyField="id"
                                     data="{!v.leadList}"
                                     columns="{!v.leadColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
        </lightning:layout>
    </aura:if>
 
</aura:component>
GlobalSearchController.js
({
    init: function (component, event, helper){
        component.set('v.accountColumns', [
            {label: 'Name', fieldName: 'Name', type: 'text'},
            {label: 'Account Number', fieldName: 'AccountNumber', type: 'text'},
            {label: 'Website', fieldName: 'Website', type: 'url', typeAttributes: { target: '_self'}}
        ]);
        component.set('v.contactColumns', [
            {label: 'Name', fieldName: 'Name', type: 'text'},
            {label: 'Email', fieldName: 'Email', type: 'email'},
            {label: 'Mobile', fieldName: 'MobilePhone', type: 'phone'},
        ]);
        component.set('v.oppColumns', [
            {label: 'Name', fieldName: 'Name', type: 'text'},
            {label: 'Stage Name', fieldName: 'StageName', type: 'text'},
            {label: 'Close Date', fieldName: 'CloseDate', type: 'date'}
        ]);
        component.set('v.leadColumns', [
            {label: 'Name', fieldName: 'Name', type: 'text'},
            {label: 'Company', fieldName: 'Company', type: 'text'},
            {label: 'Email', fieldName: 'Email', type: 'email'}
        ]);
    },
 
    search : function(component, event, helper) {
        helper.getSearchResultsFromApex(component, event, helper);
        component.set("v.showSearchResults",true);
    }
})
GlobalSearchHelper.js
({
    getSearchResultsFromApex : function(component, event, helper){
     
        var action = component.get("c.getSearchResult");
        action.setParams({ searchKey : component.get("v.searchKey") });
     
        // Create a callback that is executed after
        // the server-side action returns
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var result = response.getReturnValue();
                // SOSL will always return the list in the order they were queried
                component.set("v.accountList",result[0]);
                component.set("v.contactList",result[1]);
                component.set("v.oppList",result[2]);
                component.set("v.leadList",result[3]);
            }
            else if (state === "INCOMPLETE") {
                // do something
            }
                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);
    }
})
GlobalSearch.css
.THIS .customButton{
    margin-top: 19px;
}
GlobalSearchController.apxc
public class GlobalSearchController {
 
    @AuraEnabled(cacheable=true)
    public static List<List<sObject>> getSearchResult(String searchKey){
     
        List<List<sObject>> searchResult = [FIND :searchKey
                                            IN ALL FIELDS RETURNING
                                            Account (Id, Name, AccountNumber, Website),
                                            Contact(Id, Name, Email, MobilePhone),
                                            Opportunity(Id, Name, StageName, CloseDate),
                                            Lead(Id, Name, Email, Company)];
        return searchResult;
     
    }
}

Comments

Popular posts from this blog

Salesforce Hacks: System.LimitException: Too many queueable jobs added to the queue: 2

Salesforce Lightning: Countdown timer

Building an Org Role Hierarchy component in LWC