Disable LookUp Input Field on Visualforce Page

Sample Code:

<apex:page standardController="Contact" id="pg">
    <apex:form id="fm">
        <apex:inputField value="{!Contact.AccountId}" id="ifAcc" />
    </apex:form>
    <script>
    var inpAcc = document.getElementById("pg:fm:ifAcc");
    inpAcc.setAttribute("readonly","true");   
    </script>  
</apex:page>

Output:

Inherited Lightning Component Attributes

A Child component that extends a Parent component inherits the attributes of the Parent component.

Let’s start with a simple example. Here in below example c:Parent has a description attribute with a value of “Hello!!”, and c:Child extends c:Parent by setting extends="c:Parent" in its aura:component tag.

Parent Component:

<!--Parent.cmp-->
<aura:component extensible="true">
    <aura:attribute name="description" type="String" default="Hello!!" />
    <p>Description: {!v.description}</p>
</aura:component>

Child Component:

<!--Child.cmp-->
<aura:component extends="c:Parent">
    <aura:set attribute="description" value="Hello World!" />
</aura:component>

Test App:

<!--Test.app-->
<aura:application extends="force:slds">
    <c:Parent />
    <c:Child />    
</aura:application>

Output:
Description: Hello!!
Description: Hello World!

Pagination In Lightning Component

Pagination Component:
Create a new Lightning Component Pagination.cmp.

<!--Pagination.cmp-->
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" 
                controller='PaginationController'
                access="global" >
    
    <!-- Attribute Declration For Pagination -->
    <aura:attribute name="ContactData" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    
    <aura:attribute name="isSending" type="boolean" />
    
    <!-- Attribute Declration For Pagination -->
    <aura:attribute name="PaginationList" type="Contact"/>
    <aura:attribute name="startPage" type="Integer" />
    <aura:attribute name="endPage" type="Integer"/>
    <aura:attribute name="totalRecords" type="Integer"/>
    <aura:attribute name="pageSize" type="Integer" default="10"/>
    <!-- Attribute Declration For Pagination End-->
    
    <aura:handler name="init" value="{! this }" action="{! c.doInit }"/>
    
    <!-- Spinner Start, show the loading screen while 
   Client side controller(JS) is communicating with Server Side(APEX) controller -->
    <aura:if isTrue="{!v.isSending}">
        <div class="slds-spinner_container">
            <div class="slds-spinner--brand slds-spinner slds-spinner--large" 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>
    <!-- Spinner End -->
    
    <div class="slds-page-header">
        <div class="slds-media">
            <div class="slds-media__figure">
                <span class="slds-icon_container slds-icon-standard-opportunity" 
                      title="Description of icon when needed">
                    
                </span>
            </div>
        </div>
    </div>
    
    <div class="slds-m-top_medium" >
        <lightning:datatable data="{! v.PaginationList }" class="slds-m-top_medium"
                             columns="{! v.columns }" 
                             keyField="id"
                             onrowselection="{! c.getSelectedName }"/>	
        <br/>
        <lightning:buttonGroup >
            <lightning:button label="Previous" disabled="{!v.startPage == 0}"  
                              onclick="{!c.previous}" variant="brand"
                              iconName='utility:back'/>
            &nbsp; &nbsp; &nbsp;
            <lightning:button label="Next" disabled="{!v.endPage >= v.totalRecords}" 
                              onclick="{!c.next}" variant="brand"
                              iconName='utility:forward' iconPosition='right'/>
        </lightning:buttonGroup>
    </div>
</aura:component>

Pagination JavaScript Controller:
Now create below JavaScript PaginationController.js controller for above Pagination.cmp component.

({
    doInit: function (component, event, helper) {
        // Set the columns of the Table 
        component.set('v.isSending',true);
        component.set('v.columns', [
            {label: 'Name', fieldName: 'Name', type: 'text', sortable : true},
            {label: 'Email', fieldName: 'Email', type: 'email', sortable : true},
            {label: 'Phone', fieldName: 'Phone', type: 'phone', sortable : true}]);
        helper.doFetchContact(component);
    },
    getSelectedName: function (component, event) {
        var selectedRows = event.getParam('selectedRows');
        // Display that fieldName of the selected rows
        for (var i = 0; i < selectedRows.length; i++){
            alert("You selected: " + selectedRows[i].Name);
        }
    },
    next: function (component, event, helper) {
        helper.next(component, event);
    },
    previous: function (component, event, helper) {
        helper.previous(component, event);
    }
})

Pagination JavaScript Controller Helper:
Now create below JavaScript PaginationHelper.js helper for above PaginationController.js component.

({
    /*
     * Initially this Method will be called and will fetch the records from the Salesforce Org 
     * Then we will hold all the records into the attribute of Lightning Component
     */
    doFetchContact : function(component) {
        var action = component.get('c.getContacts');
        action.setCallback(this, function(response){
            var state = response.getState();
            if(state === 'SUCCESS' && component.isValid()){
                var pageSize = component.get("v.pageSize");
                // hold all the records into an attribute named "ContactData"
                component.set('v.ContactData', response.getReturnValue());
                // get size of all the records and then hold into an attribute "totalRecords"
                component.set("v.totalRecords", component.get("v.ContactData").length);
                // set star as 0
                component.set("v.startPage",0);
                
                component.set("v.endPage",pageSize-1);
                var PaginationList = [];
                for(var i=0; i< pageSize; i++){
                    if(component.get("v.ContactData").length> i)
                        PaginationList.push(response.getReturnValue()[i]);    
                }
                component.set('v.PaginationList', PaginationList);
                component.set('v.isSending',false);
            }else{
                alert('ERROR');
            }
        });
        $A.enqueueAction(action);
    },
    /*
     * Method will be called when use clicks on next button and performs the 
     * calculation to show the next set of records
     */
    next : function(component, event){
        var sObjectList = component.get("v.ContactData");
        var end = component.get("v.endPage");
        var start = component.get("v.startPage");
        var pageSize = component.get("v.pageSize");
        var Paginationlist = [];
        var counter = 0;
        for(var i=end+1; i<end+pageSize+1; i++){
            if(sObjectList.length > i){
                Paginationlist.push(sObjectList[i]);
            }
            counter ++ ;
        }
        start = start + counter;
        end = end + counter;
        component.set("v.startPage",start);
        component.set("v.endPage",end);
        component.set('v.PaginationList', Paginationlist);
    },
    /*
     * Method will be called when use clicks on previous button and performs the 
     * calculation to show the previous set of records
     */
    previous : function(component, event){
        var sObjectList = component.get("v.ContactData");
        var end = component.get("v.endPage");
        var start = component.get("v.startPage");
        var pageSize = component.get("v.pageSize");
        var Paginationlist = [];
        var counter = 0;
        for(var i= start-pageSize; i < start ; i++){
            if(i > -1){
                Paginationlist.push(sObjectList[i]);
                counter ++;
            }else{
                start++;
            }
        }
        start = start - counter;
        end = end - counter;
        component.set("v.startPage",start);
        component.set("v.endPage",end);
        component.set('v.PaginationList', Paginationlist);
    }
})

Pagination Apex Controller:
Create below apex controller to use it in Pagination.cmp component.

public class PaginationController {
    @AuraEnabled
    public static List<Contact> getContacts(){
        List<Contact> contactList = new List<Contact>();
        contactList = [SELECT Id, Name, Email, Phone From Contact LIMIT 50];
        return contactList;
    }
}

Pagination App:

<!--PaginationApp.app-->
<aura:application extends="force:slds">
    <c:Pagination />    
</aura:application>

Output:

Upload Multiple Files Using Lightning File Upload Component

In Winter ’18 Salesforce released a new lightning component lightning:fileUpload, which provides an easy and integrated way for users to upload multiple files. The file uploader includes drag-and-drop functionality and filtering by file types.

File Upload Component Limits:

  • By default, you can upload up to 10 files simultaneously unless your Salesforce admin has changed that limit.
  • The org limit for the number of files simultaneously uploaded is a maximum of 25 files and a minimum of 3 files.
  • The maximum file size you can upload is 2 GB. In Communities, the file size limits and types allowed follow the settings determined by community file moderation.

Considerations:

  • This component is not supported in Lightning Out or standalone apps, and displays as a disabled input.
  • The file uploader cannot be used to upload files with the following file extensions: .htm, .html, .htt, .htx, .mhtm, .mhtml, .shtm, .shtml, .acgi, .svg.

In this article I will show you how you can upload multiple files using lightning file upload component, without writing the apex code.

FileUpload Component:
Create a new Lightning Component FileUpload.cmp.

<!--FileUpload.cmp-->
<aura:component controller="FileUploadController" implements="force:appHostable, flexipage:availableForAllPageTypes, flexipage:availableForRecordHome, force:hasRecordId, forceCommunity:availableForAllPageTypes, force:lightningQuickAction" access="global">
    
    <lightning:fileUpload label="Upload File" multiple="true" accept=".pdf, .png" recordId="{!v.recordId}" aura:id="multifileUpload" onuploadfinished="{!c.handleUploadFinished}" />
</aura:component>

FileUpload JavaScript Controller:
Now create below JavaScript FileUploadController.js controller for above FileUpload.cmp component.

({    
    handleUploadFinished: function (cmp, event) {
        //Get the list of uploaded files
        var uploadedFiles = event.getParam("files");
        //Show success message – with no of files uploaded
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Success!",
            "type" : "success",
            "message": uploadedFiles.length+" files has been uploaded successfully!"
        });
        toastEvent.fire();
        
        $A.get('e.force:refreshView').fire();
        
        //Close the action panel
        var dismissActionPanel = $A.get("e.force:closeQuickAction");
        dismissActionPanel.fire();
    }
})

Steps to test the functionality:
Go to Setup || Object Manager || Select Object(For example Account) || Buttons, Links, and Actions || New Action || Create Quick Action

Now add the created Quick Action into Object Page Layout.
Go to Setup || Object Manager || Select Object(For example Account) || Page Layouts || Select Your Layouts (For example Account Layout) || Select Mobile & lightning Actions || Add the Quick Action into Salesforce Mobile & Lightning Experience Actions section.

Now, Open an account record click Upload File action from right upload files and try to upload file.

Salesforce Generic sObject Lightning Lookup Component

In Salesforce Lightning we don’t have any lookup field component like Salesforce classic. So, here is a generic lookup Lightning Component, which can be used for any sObject lookup present in our org without changing any major code.

sObjectLookup.cmp:
Create below Lightning Component, which will be used for sObject lookup.

<!--sObjectLookup.cmp-->
<aura:component description="Lookup. Lightning component for lookup fields. Can be used standalone or with other lightning component" controller="sObjectLookupController">
    
    <aura:attribute name="objectAPIName" type="String" required="true" description="Object API name used for searching records"/>
    
    <aura:attribute name="placeholder" type="String" default="Search..." description="Placeholder text for input search filed"/>
    
    <aura:attribute name="fieldLabel" type="String" required="true" description="input search field Label"/>
    
    <aura:attribute name="filter" type="String[]" default="[]" description="Array of filter for SOSL query. All the filters should be given in this field separated by comma(,) Example: AccountId='00128000002KuXU' "/>
    
    <aura:attribute name="selectedRecordId" type="String" description="Used to store the selected record id. While calling this component from other component, set this attribute to the lookup field API name"/>
    
    <aura:attribute name="selectedRecordLabel" type="String" description="This is used to show the selected record Name in search input"/>
    
    <aura:attribute name="subHeadingFieldsAPI" type="String[]" description="Field API for the fields to be shown under the record Name. Must be comma separated. Example: Email,Phone"/>
    
    <aura:attribute name="matchingRecords" type="Object[]" access="private" description="List of records returned from server side call."/>
    
    <aura:handler name="lookupSelect" event="c:sObjectLookupSelectEvent" action="{!c.handleLookupSelectEvent}" description="Event handler to get the selected record Id and Name from LookupItem component"/>
    
    
<div class="slds-form-element__control">
        
<div class="slds-combobox_container slds-has-inline-listbox">
            
<div aura:id="lookupdiv" class="slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-combobox-lookup" aria-expanded="false" aria-haspopup="listbox" role="combobox">
                
                
<div class="slds-combobox__form-element">
                    <!-- using input type "search" to place the search icon input field-->
                    <lightning:input type="search" aura:id="searchinput" label="{!v.fieldLabel}" name="{!v.fieldLabel}" value="{!v.selectedRecordLabel}" onchange="{!c.searchRecords}" isLoading="false" placeholder="{!v.placeholder}" onfocus="{!c.searchRecords}" onblur="{!c.hideList}"/>
                </div>

                
<div id="listbox-unique-id" role="listbox">
                    
<ul class="slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid" role="presentation">
                        <!-- LookupItem component for creating record list -->
                        <aura:iteration var="rec" items="{!v.matchingRecords}">
                            <c:sObjectLookupItem record="{!rec}" subHeadingFieldsAPI="{!v.subHeadingFieldsAPI}" iconCategoryName="standard:contact"/>
                        </aura:iteration>
                    </ul>

                </div>

            </div>

        </div>

    </div>

</aura:component>

sObjectLookupController.js:
Now create below JavaScript controller for above sObjectLookup.cmp component.

({
    //Function to handle the sObjectLookupSelectEvent. Sets the chosen record Id and Name
    handleLookupSelectEvent : function (component,event,helper) {
        component.set("v.selectedRecordId", event.getParam("recordId"));
        component.set("v.selectedRecordLabel",event.getParam("recordLabel"));
        helper.toggleLookupList(component,
                                false,
                                'slds-combobox-lookup',
                                'slds-is-open');
    },
    
    //Function for finding the records as for given search input
    searchRecords : function (component,event,helper) {
        var searchText = component.find("searchinput").get("v.value");
        
        if(searchText){
            helper.searchSOSLHelper(component,searchText);
        }else{
            helper.searchSOQLHelper(component);
        }
    },
    
    //function to hide the list on onblur event.
    hideList :function (component,event,helper) {
        //Using timeout and $A.getCallback() to avoid conflict between LookupChooseEvent and onblur
        window.setTimeout(
            $A.getCallback(function() {
                if (component.isValid()) {
                    helper.toggleLookupList(component,
                                            false,
                                            'slds-combobox-lookup',
                                            'slds-is-open'
                                           );
                }
            }), 200
        );
    }
})

sObjectLookupHelper.js:
Now create below JavaScript helper for above sObjectLookupController.js JavaScript controller.

({
    //Function to toggle the record list drop-down
    toggleLookupList : function (component, ariaexpanded, classadd, classremove) {
        component.find("lookupdiv").set("v.aria-expanded", true);
        $A.util.addClass(component.find("lookupdiv"), classadd);
        $A.util.removeClass(component.find("lookupdiv"), classremove);
    },
    
    //function to call SOSL apex method.
    searchSOSLHelper : function (component,searchText) {
        //validate the input length. Must be greater then 3.
        //This check also manages the SOSL exception. Search text must be greater then 2.
        if(searchText && searchText.length > 3){
            //show the loading icon for search input field
            component.find("searchinput").set("v.isLoading", true);
            
            //server side callout. returns the list of record in JSON string
            var action = component.get("c.search");
            action.setParams({
                "objectAPIName": component.get("v.objectAPIName"),
                "searchText": searchText,
                "whereClause" : component.get("v.filter"),
                "extrafields":component.get("v.subHeadingFieldsAPI")
            });
            
            action.setCallback(this, function(a){
                var state = a.getState();
                
                if(component.isValid() && state === "SUCCESS") {
                    //parsing JSON return to Object[]
                    var result = [].concat.apply([], JSON.parse(a.getReturnValue()));
                    component.set("v.matchingRecords", result);
                    console.log( component.get("v.matchingRecords"));
                    
                    //Visible the list if record list has values
                    if(a.getReturnValue() && a.getReturnValue().length > 0){
                        this.toggleLookupList(component,
                                              true,
                                              'slds-is-open',
                                              'slds-combobox-lookup');
                        
                        //hide the loading icon for search input field
                        component.find("searchinput").set("v.isLoading", false);
                    }else{
                        this.toggleLookupList(component, false,
                                              'slds-combobox-lookup',
                                              'slds-is-open');
                    }
                }else if(state === "ERROR") {
                    console.log('error in searchRecords');
                }
            });
            $A.enqueueAction(action);
        }else{
            //hide the drop down list if input length less then 3
            this.toggleLookupList(component,
                                  false,
                                  'slds-combobox-lookup',
                                  'slds-is-open'
                                 );
        }
    },
    
    //function to call SOQL apex method.
    searchSOQLHelper : function (component) {
        component.find("searchinput").set("v.isLoading", true);
        //var searchText = component.find("searchinput").get("v.value");
        
        var action = component.get("c.getRecentlyViewed");
        action.setParams({
            "objectAPIName": component.get("v.objectAPIName"),
            "whereClause" : component.get("v.filter"),
            "extrafields":component.get("v.subHeadingFieldsAPI")
        });
        
        //console.log(searchText);
        
        // Configure response handler
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(component.isValid() && state === "SUCCESS") {
                if(response.getReturnValue()){
                    component.set("v.matchingRecords", response.getReturnValue());
                    console.log( component.get("v.matchingRecords"));
                    if(response.getReturnValue().length>0){
                        this.toggleLookupList(component,
                                              true,
                                              'slds-is-open',
                                              'slds-combobox-lookup');
                    }
                    component.find("searchinput").set("v.isLoading", false);
                }
            } else {
                console.log('Error in loadRecentlyViewed: ' + state);
            }
        });
        $A.enqueueAction(action);
    }
})

sObjectLookupSelectEvent.evt:
Create below Lightning Event, which is used to store and fill the input field with selected record Id and Name. Fired from sObjectLookupItem.cmp component, handled at Lookup component.

<aura:event type="COMPONENT" description="sObjectLookupSelectEvent">
    <aura:attribute name="recordId" type="String" required="true" description="Used to send selected record Id"/>
    
    <aura:attribute name="recordLabel" type="String" description="Used to send selected record Name" required="true"/>
</aura:event>

sObjectLookupItem.cmp:
Create below lightning component, which will be used for creating list elements for records in sObjectLookup.cmp component.

<!--sObjectLookupItem.cmp-->
<aura:component description="sObjectLookupItem. Component used for creating list elements for records. Used in Lookup component">
    
    <!-- Component attributes-->
    <aura:attribute name="record" type="Object" description="Holds the single record instance" required="true"/>
    
    <aura:attribute name="subHeadingFieldsAPI" type="String[]" description="Holds the field API names to show as meta entity in list"/>
    
    <aura:attribute name="subHeadingFieldValues" type="String" description="Used to construct the meta entity value. Works as subheading in record option"/>
    
    <aura:attribute name="iconCategoryName" type="String" description="Lightning icon category and icon name to show with each record element"/>
    
    <!-- Component event registers-->
    <aura:registerEvent name="lookupSelect" type="c:sObjectLookupSelectEvent" description="Event used to send the selected record Id and Name to Lookup component"/>
    
    <!-- Component event handlers-->
    <aura:handler name="init" value="{!this}" action="{!c.loadValues}" description="standard init event to prepare the sub heading mete entity value"/>
    
    <!-- Component markup-->
    
<li role="presentation" class="slds-listbox__item" onclick="{!c.choose}">
        <span class="slds-media slds-listbox__option slds-listbox__option_entity slds-listbox__option_has-meta" role="option">
            <!-- lightning icon -->
            <span class="slds-media__figure">
                <lightning:icon iconName="{!v.iconCategoryName}" size="small" alternativeText="{!v.record.Name}"/>
            </span>
            <!-- option Name-->
            <span class="slds-media__body">
                <span class="slds-listbox__option-text slds-listbox__option-text_entity">
                    {!v.record.Name}
                </span>
                <!-- option sub heading. Also known as meta entity as per SLDS combobox component-->
                <span class="slds-listbox__option-meta slds-listbox__option-meta_entity">
                    {!v.subHeadingFieldValues}
                </span>
            </span>
        </span>
    </li>

</aura:component>

sObjectLookupItemController.js:
Now create below JavaScript controller for above sObjectLookupItem.cmp component.

({
    loadValues : function (component) {
        var record = component.get("v.record");
        var subheading = '';
        for(var i=0; i<component.get("v.subHeadingFieldsAPI").length ;i++ ){
            if(record[component.get("v.subHeadingFieldsAPI")[i]]){
                subheading = subheading + record[component.get("v.subHeadingFieldsAPI")[i]] + ' • ';
            }
        }
        subheading = subheading.substring(0,subheading.lastIndexOf('•'));
        component.set("v.subHeadingFieldValues", subheading);
    },
    
    choose : function (component,event) {
        var chooseEvent = component.getEvent("lookupSelect");
        chooseEvent.setParams({
            "recordId" : component.get("v.record").Id,
            "recordLabel":component.get("v.record").Name
        });
        chooseEvent.fire();
        console.log('event fired');
    }
})

sObjectLookupController:
Create below apex controller to use it in sObjectLookup.cmp component.

public with sharing class sObjectLookupController {
    
    /* Method to query records using SOSL*/
    @AuraEnabled
    public static String search(String objectAPIName, String searchText,
                                List<String> whereClause, List<String> extrafields){
                                    
                                    objectAPIName = String.escapeSingleQuotes(objectAPIName);
                                    searchText = String.escapeSingleQuotes(searchText);
                                    String searchQuery = 'FIND \'' + searchText + '*\' IN ALL FIELDS RETURNING ' + objectAPIName + '(Id,Name' ;
                                    if(!extrafields.isEmpty()){
                                        searchQuery = searchQuery + ',' + String.join(extrafields, ',') ;
                                    }
                                    system.debug(whereClause);
                                    if(!whereClause.isEmpty()){
                                        searchQuery = searchQuery + ' WHERE ' ;
                                        searchQuery = searchQuery + String.join(whereClause, 'AND') ;
                                    }
                                    searchQuery = searchQuery + ' LIMIT 10 ) ';
                                    system.debug(searchQuery);
                                    return JSON.serializePretty(search.query(searchQuery)) ;
                                }
    
    /* Method to query records using SOQL*/
    @AuraEnabled
    public static List<SObject> getRecentlyViewed(
        String objectAPIName,
        List<String> whereClause,
        List<String> extrafields){
            
            String searchQuery = 'SELECT Id, Name';
            if(!extrafields.isEmpty()){
                searchQuery = searchQuery + ',' + String.join(extrafields, ',') ;
            }
            searchQuery = searchQuery + ' FROM ' + objectAPIName + ' WHERE LastViewedDate != NULL ';
            if(!whereClause.isEmpty()){
                searchQuery = searchQuery + ' AND ' ;
                searchQuery = searchQuery + String.join(whereClause, 'AND') ;
                system.debug(searchQuery);
            }
            searchQuery = searchQuery + ' ORDER BY LastViewedDate DESC' ;
            List<SObject> objectList =  new List<SObject>();
            objectList = Database.query(searchQuery);
            return objectList;
        }
}

Implementation Notes:

  • On focusing the input field it shows the recent items viewed for given Object. This replcates the standard behavior noticed in standard lightning lookup fields. If filter attribute is given then recent items will respect the filter condition.
  • SOSL and SOQL both are utilizied to search for records. SOQL is used to fetch the recently viewed records because SOSL cannoot accept blank text. SOSL is used if input field has text. Also, because searching can be done on non-index fields SOSL gives better performance in terms of speed and record list. With SOSL text fields are considered as indexed.
  • Input text must be greater than 3 in size. Noticed that SOSL throws an error with less than 3 search string length.
  • To show and hide the record drop-down list SLDS “slds-combobox-lookup”, “slds-is-open” classes and “v.aria-expanded” attribute is used.
  • $A.getCallback() is used to hide the record list on “onblur” of input field. Because we have an event firing on click of list item, onblur conflict is noticed and doesn’t allows to fire the sObjectLookupSelectEvent.evt event.
  • Maintains the record sharing security.

Usage:

<!--sObjectLookupApp.app-->
<aura:application implements="force:appHostable" extends="force:slds" description="sObjectLookupApp">
    <!-- with Filter -->
    <c:sObjectLookup fieldLabel="Contact" objectAPIName="Contact" subHeadingFieldsAPI="Email,Phone" placeholder="Search Contact" filter="AccountId='00128000002KuXU'"/>
    
    <!-- without Filter -->
    <c:sObjectLookup fieldLabel="Contact" objectAPIName="Contact" subHeadingFieldsAPI="Email,Phone" placeholder="Search Contact"/>
</aura:application>

Output: