Apex Class :
Create a below apex controllerreUsableMultiSelectLookupCtrl.apex
public class reUsableMultiSelectLookupCtrl {
@AuraEnabled
public static List < sObject > fetchLookUpValues(String searchKeyWord, String ObjectName, List ExcludeitemsList) {
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%;
}
Output :