Apex Class :
Create a below apex controllerreUsableMultiSelectLookupCtrl.apex
public class reUsableMultiSelectLookupCtrl { @AuraEnabled public static List < sObject > fetchLookUpValues(String searchKeyWord, String ObjectName, ListExcludeitemsList) { String searchKey = '%' + searchKeyWord + '%'; List < sObject > returnList = new List < sObject > (); List lstExcludeitems = new List (); for(sObject item : ExcludeitemsList ){ lstExcludeitems.add(item.id); } // Create a Dynamic SOQL Query For Fetch Record List with LIMIT 5 and exclude already selected records String sQuery = 'select id, Name from ' +ObjectName + ' where Name LIKE: searchKey AND Id NOT IN : lstExcludeitems order by createdDate DESC limit 5'; List < sObject > lstOfRecords = Database.query(sQuery); for (sObject obj: lstOfRecords) { returnList.add(obj); } return returnList; } }
Lightning Event :
Create a belowselectedsObjectRecordsEvent.evt
<aura:event type="COMPONENT" description="by this event we are pass the selected sObject(lookup list record) in the parent component"> <aura:attribute name="recordByEvent" type="sObject"/> </aura:event>
Lightning Component [Child] :
Create a belowreUsableMultiSelectLookupResult.cmp
<aura:component access="global"> <!--aura attributes--> <aura:attribute name="oRecord" type="sObject" /> <aura:attribute name="IconName" type="string"/> <!--Register the component level event--> <aura:registerEvent name="oSelectedRecordEvent" type="c:selectedsObjectRecordsEvent"/> <li role="presentation" class="slds-listbox__item" onclick="{!c.selectRecord}"> <span id="listbox-option-unique-id-01" class="slds-media slds-listbox__option slds-listbox__option_entity slds-listbox__option_has-meta" role="option"> <span class="slds-media__figure"> <span class="slds-icon_container" title="Description of icon when needed"> <lightning:icon iconName="{!v.IconName}" class="slds-icon slds-icon_small" size="small" alternativeText="icon"/> </span> </span> <span class="slds-media__body"> <span class="slds-listbox__option-text slds-listbox__option-text_entity">{!v.oRecord.Name}</span> </span> </span> </li> </aura:component>
JavaScript Controller :
Create a belowreUsableMultiSelectLookupResultController.js
({ selectRecord : function(component, event, helper){ // get the selected record from list var getSelectRecord = component.get("v.oRecord"); // call the event var compEvent = component.getEvent("oSelectedRecordEvent"); // set the Selected sObject Record to the event attribute. compEvent.setParams({"recordByEvent" : getSelectRecord }); // fire the event compEvent.fire(); }, })
Lightning Component :
Create a belowreUsableMultiSelectLookup.cmp[Parent]
<aura:component controller="reUsableMultiSelectLookupCtrl"> <!--declare attributes--> <aura:attribute name="lstSelectedRecords" type="sObject[]" default="[]" description="Use,for store SELECTED sObject Records"/> <aura:attribute name="listOfSearchRecords" type="List" description="Use,for store the list of search records which returns from apex class"/> <aura:attribute name="SearchKeyWord" type="string"/> <aura:attribute name="objectAPIName" type="string" default=""/> <aura:attribute name="IconName" type="string" default=""/> <aura:attribute name="label" type="string" default=""/> <!--declare events hendlers--> <aura:handler name="oSelectedRecordEvent" event="c:selectedsObjectRecordsEvent" action="{!c.handleComponentEvent}"/> <aura:attribute name="Message" type="String" default=""/> <!-- https://www.lightningdesignsystem.com/components/lookups/ --> <div onmouseleave="{!c.onblur}" aura:id="searchRes" class="slds-form-element slds-lookup slds-is-close"> <label class="slds-form-element__label">{!v.label}</label> <!--This part is for display search bar for lookup--> <div class="slds-form-element__control"> <div class="slds-input-has-icon slds-input-has-icon--right"> <!-- This markup is for when an record is selected --> <div aura:id="lookup-pill" class="slds-pill-container"> <div aura:id="lookupField" class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right" style="width: 100%;"> <ui:inputText click="{!c.onfocus}" updateOn="keyup" keyup="{!c.keyPressController}" class="slds-lookup__search-input slds-input inputSize" value="{!v.SearchKeyWord}" placeholder="search.."/> <span class="slds-icon_container slds-icon-utility-search slds-input__icon slds-input__icon_right"> <lightning:icon iconName="utility:search" size="x-small" alternativeText="icon"/> </span> </div> <!--Selected Records Pills Section--> <aura:iteration items="{!v.lstSelectedRecords}" var="sr"> <lightning:pill class="slds-m-around_xx-small" label="{!sr.Name}" name="{!sr.Id}" onremove="{! c.clear }"> <aura:set attribute="media"> <lightning:icon iconName="{!v.IconName}" size="x-small" alternativeText="icon"/> </aura:set> </lightning:pill> </aura:iteration> </div> </div> </div> <!--This part is for Display typehead lookup result List--> <ul style="min-height:40px;margin-top:0px !important" class="slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid slds-lookup__menu slds" role="listbox"> <lightning:spinner class="slds-hide" variant="brand" size="small" aura:id="mySpinner"/> <center> {!v.Message}</center> <aura:iteration items="{!v.listOfSearchRecords}" var="singleRec"> <!--Child Component--> <c:reUsableMultiSelectLookupResult oRecord="{!singleRec}" IconName="{!v.IconName}"/> </aura:iteration> </ul> </div> </aura:component>
JavaScript Controller :
Create a belowreUsableMultiSelectLookupController.js
({ onblur : function(component,event,helper){ // on mouse leave clear the listOfSeachRecords & hide the search result component component.set("v.listOfSearchRecords", null ); component.set("v.SearchKeyWord", ''); var forclose = component.find("searchRes"); $A.util.addClass(forclose, 'slds-is-close'); $A.util.removeClass(forclose, 'slds-is-open'); }, onfocus : function(component,event,helper){ // show the spinner,show child search result component and call helper function $A.util.addClass(component.find("mySpinner"), "slds-show"); component.set("v.listOfSearchRecords", null ); var forOpen = component.find("searchRes"); $A.util.addClass(forOpen, 'slds-is-open'); $A.util.removeClass(forOpen, 'slds-is-close'); // Get Default 5 Records order by createdDate DESC var getInputkeyWord = ''; helper.searchHelper(component,event,getInputkeyWord); }, keyPressController : function(component, event, helper) { $A.util.addClass(component.find("mySpinner"), "slds-show"); // get the search Input keyword var getInputkeyWord = component.get("v.SearchKeyWord"); // check if getInputKeyWord size id more then 0 then open the lookup result List and // call the helper // else close the lookup result List part. if(getInputkeyWord.length > 0){ var forOpen = component.find("searchRes"); $A.util.addClass(forOpen, 'slds-is-open'); $A.util.removeClass(forOpen, 'slds-is-close'); helper.searchHelper(component,event,getInputkeyWord); } else{ component.set("v.listOfSearchRecords", null ); var forclose = component.find("searchRes"); $A.util.addClass(forclose, 'slds-is-close'); $A.util.removeClass(forclose, 'slds-is-open'); } }, // function for clear the Record Selaction clear :function(component,event,heplper){ var selectedPillId = event.getSource().get("v.name"); var AllPillsList = component.get("v.lstSelectedRecords"); for(var i = 0; i < AllPillsList.length; i++){ if(AllPillsList[i].Id == selectedPillId){ AllPillsList.splice(i, 1); component.set("v.lstSelectedRecords", AllPillsList); } } component.set("v.SearchKeyWord",null); component.set("v.listOfSearchRecords", null ); }, // This function call when the end User Select any record from the result list. handleComponentEvent : function(component, event, helper) { component.set("v.SearchKeyWord",null); // get the selected object record from the COMPONENT event var listSelectedItems = component.get("v.lstSelectedRecords"); var selectedAccountGetFromEvent = event.getParam("recordByEvent"); listSelectedItems.push(selectedAccountGetFromEvent); component.set("v.lstSelectedRecords" , listSelectedItems); var forclose = component.find("lookup-pill"); $A.util.addClass(forclose, 'slds-show'); $A.util.removeClass(forclose, 'slds-hide'); var forclose = component.find("searchRes"); $A.util.addClass(forclose, 'slds-is-close'); $A.util.removeClass(forclose, 'slds-is-open'); }, })
JavaScript Helper :
Create a belowreUsableMultiSelectLookupHelper.js
({ searchHelper : function(component,event,getInputkeyWord) { // call the apex class method var action = component.get("c.fetchLookUpValues"); // set param to method action.setParams({ 'searchKeyWord': getInputkeyWord, 'ObjectName' : component.get("v.objectAPIName"), 'ExcludeitemsList' : component.get("v.lstSelectedRecords") }); // set a callBack action.setCallback(this, function(response) { $A.util.removeClass(component.find("mySpinner"), "slds-show"); var state = response.getState(); if (state === "SUCCESS") { var storeResponse = response.getReturnValue(); // if storeResponse size is equal 0 ,display No Records Found... message on screen. } if (storeResponse.length == 0) { component.set("v.Message", 'No Records Found...'); } else { component.set("v.Message", ''); // set searchResult list with return value from server. } component.set("v.listOfSearchRecords", storeResponse); } }); // enqueue the Action $A.enqueueAction(action); }, })
Component CSS :
Create a belowreUsableMultiSelectLookup.css
.THIS .inputSize { width:100%; }