Hello Everyone, In this tutorial, I am going to provide a step-by-step procedure to create a custom Lightning component that helps you to search for records in the database. It’s a search tool that uses SOSL to query data from the database and return the result in form of a sObject list that we show in Lightning component using lightning:datatable tag.

After completing this tutorial you'll able to:
  • Create a global search lightning component.
  • Show records on UI using lightning:datatable tag.
So let's start,

Global Search Lightning Component

Login to your Salesforce Org. and open developer console.


Step1: Go to File>New>Apex Class and Create an Apex controller called GlobalSearchHandler. Replace following code in apex controller.

GlobalSearchHandler.apxc
 public class GlobalSearchHandler{
    
    @AuraEnabled(cacheable=true)
    public static List<List<sObject>> getSearchRecords(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;
      
    }
 }

Step2: Go to File>New>Lightning Component and create a Lightning Component called GlobalSearchComponentReplace the following markup in the Lightning Component.

GlobalSearchComponent.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="GlobalSearchHandler">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>    
    <aura:handler event="aura:waiting" action="{!c.showSpinner}"/>
    <aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/>
    <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"/>
    <aura:attribute name="Spinner" type="boolean" default="false"/>
    <!--loading spinner start... style=Brand Medium (blue dots)-->
    <aura:if isTrue="{!v.Spinner}">
        <div aura:id="spinnerId" class="slds-spinner_container">
            <div class="slds-spinner--brand  slds-spinner slds-spinner--large slds-is-relative" role="alert">
                <span class="slds-assistive-text">Loading</span>
                <div class="slds-spinner__dot-a"></div>
                <div class="slds-spinner__dot-b"></div>
            </div>
        </div>
    </aura:if>
    <!-- Loading spinner end-->   
    <lightning:layout multipleRows="true">
        <lightning:layoutItem padding="around-small" size="6">
            <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="SearchButton"/>
        </lightning:layoutItem>
    </lightning:layout>
    
    <aura:if isTrue="{!v.showSearchResults}">
        <lightning:layout multipleRows="true">
            <lightning:layoutItem padding="around-small" size="12">
                <span style="font-size:16px;font-weight:bold">Account</span>
                <lightning:datatable keyField="id"
                                     data="{!v.accountList}"
                                     columns="{!v.accountColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
            <lightning:layoutItem padding="around-small" size="12">
                <span style="font-size:16px;font-weight:bold">Contact</span>
                <lightning:datatable keyField="id"
                                     data="{!v.contactList}"
                                     columns="{!v.contactColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
            <lightning:layoutItem padding="around-small" size="12">
                <span style="font-size:16px;font-weight:bold">Opportunity</span>
                <lightning:datatable keyField="id"
                                     data="{!v.oppList}"
                                     columns="{!v.oppColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
            <lightning:layoutItem padding="around-small" size="12">
                 <span style="font-size:16px;font-weight:bold">Lead</span>
                <lightning:datatable keyField="id"
                                     data="{!v.leadList}"
                                     columns="{!v.leadColumns}"
                                     hideCheckboxColumn="true"/>
            </lightning:layoutItem>
        </lightning:layout>
    </aura:if>  
 </aura:component>

GlobalSearchComponentController.js
 ({
    doInit: 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.getSearchResultsFromHandler(component,helper);
        component.set("v.showSearchResults",true);
    },
    
    // this function automatic call by aura:waiting event  
    showSpinner: function(component, event, helper) {
        // make Spinner attribute true for display loading spinner 
        component.set("v.Spinner", true); 
    },
    
    // this function automatic call by aura:doneWaiting event 
    hideSpinner : function(component,event,helper){
        // make Spinner attribute to false for hide loading spinner    
        component.set("v.Spinner", false);
    }
 })
GlobalSearchComponentHelper.js
 ({
    getSearchResultsFromHandler : function(component,helper){      
        var action = component.get("c.getSearchRecords");
        action.setParams({ searchKey : component.get("v.searchKey") });
        
        // 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);
    },
 })
GlobalSearchComponent.css
 .THIS .SearchButton{
    margin-top: 18px;
 }

 .THIS.slds-spinner_container {  
  z-index: 10000;
  position: fixed;   
 }

Step3: Go to File>New>Lightning Application and create a Lightning Application called PreviewReplace the following markup in the Lightning Application.

Preview.app
 <aura:application extends="force:slds">   
    <c:GlobalSearchComponent/>
 </aura:application>
After that click on Preview button from Right Side Pallete 


Output:

See also:
Conclusion:
Hope you like this tutorial, for any query or suggestions please feel free to comment.
Thank you.