Hi ,
Lets how to prepare custom lookup component
Here in this example i am using "svg" component for icons but you can use lightning:icon tag instead
1)Create LC_svg component:
<aura:component >
<aura:attribute name="class" type="String" description="CSS classname for the SVG element" />
<aura:attribute name="xlinkHref" type="String" description="SLDS icon path. Ex: /assets/icons/utility-sprite/svg/symbols.svg#account" />
<aura:attribute name="aria-hidden" type="String" default="true" description="aria-hidden true or false. defaults to true" />
</aura:component>
Renderer:
({
render: function(component, helper) {
//grab attributes from the component markup
var classname = component.get("v.class");
var xlinkhref = component.get("v.xlinkHref");
var ariaHidden = component.get("v.aria-hidden");
//return an svg element w/ the attributes
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('class', classname);
svg.setAttribute('aria-hidden', ariaHidden);
svg.innerHTML = '<use xlink:href="'+xlinkhref+'"></use>';
return svg;
}
})
2)Create SelectedObject event and Custom Lookup Result component for getting the list of accounts based search keyword
SelectedObject.evt:
<aura:event type="COMPONENT" description="by this event we are passing the selected Record in the Obeerving Component">
<aura:attribute name="RecordByEvent" type="sObject"/>
</aura:event>
CustomLookupResult.cmp
<aura:component >
<aura:attribute name="Obj" type="sObject" />
<!--Register the component level event-->
<aura:registerEvent name="oSelectedObjectEvent" type="c:SelectedObject"/>
<li role="presentation">
<span class="slds-lookup__item-action slds-media slds-media--center" id="lookup-option-350" role="option">
<div class="slds-media__body">
<div class="slds-input-has-icon slds-input-has-icon--right">
<c:LC_svg class="slds-input__icon" xlinkHref="{!$Resource.SLDS092 + '/assets/icons/standard-sprite/svg/symbols.svg#account'}" />
<div class="slds-lookup__result-text"><a onclick="{!c.selectRecord}">{!v.Obj.Name}</a></div>
</div>
</div>
</span>
</li>
</aura:component>
CustomLookupResultController.js:
----------------------------------------------------
({
selectRecord : function(component, event, helper){
// get the selected Account from list
var getSelectRecord = component.get("v.Obj");
// call the event
var compEvent = component.getEvent("oSelectedObjectEvent");
// set the Selected Object to the event attribute.
compEvent.setParams({"RecordByEvent" : getSelectRecord });
// fire the event
compEvent.fire();
},
})
3)Create PickListEvt.evt and CustomLookup.cmp component:
PickListEvt.evt:
---------------------
<aura:event type="Component" description="Event fire when some one selects a value in picklist" >
<aura:attribute name="SelectedValue" type="string" description="The result of the Selection"/>
</aura:event>
CustomLookup.cmp
---------------------------
/*
This is the Controller Class for the Custom Lookup component.
*/
public class LookUpController {
@AuraEnabled
public static List <sObject> fetchRecords(String searchKeyWord, String ObjName, string count) {
String searchKey = searchKeyWord + '%';
List < Sobject > lstOfObj = Database.query('SELECT id, Name '+' FROM '+ObjName+' WHERE Name LIKE \''+searchKey+'\' limit ' + count);
return lstOfObj ;
}
}
<aura:component controller="LookUpController" >
<aura:registerEvent name="RecordSelected" type="c:PickListEvt" description="This will Fire when the records has reached in it"/>
<aura:attribute name="selectedRecord" type="sObject" default="{}" description="Use,for store SELECTED sObject Record"/>
<aura:attribute name="listOfSearchRecords" type="sObject[]" description="Use,for store the list of search records which returns from apex class"/>
<aura:attribute name="SearchKeyWord" type="string"/>
<aura:attribute name="FieldLabel" type="String"/>
<aura:attribute name="ObjName" type="string" default="Account"/>
<aura:attribute name="RecordCount" type="string" default="10"/>
<aura:attribute name="Message" type="String" default="Search Result.."/>
<!--declare events handlers-->
<aura:handler name="oSelectedObjectEvent" event="c:SelectedObject" action="{!c.handleComponentEvent}"/>
<aura:handler event="aura:waiting" action="{!c.showSpinner}"/>
<aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/>
<div class="slds-m-around">
<div aura:id="searchRes" class="slds-form-element slds-lookup slds-is-close" data-select="single">
<aura:if isTrue="{!!empty(v.FieldLabel)}">
<label class="slds-form-element__label" for="lookup-348"> {!v.FieldLabel}</label>
</aura:if>
<!--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">
<c:LC_svg class="slds-input__icon slds-show" xlinkHref="{!$Resource.SLDS092 + '/assets/icons/utility-sprite/svg/symbols.svg#search'}" />
<!-- This markup is for when an record is selected -->
<div aura:id="lookup-pill" class="slds-pill-container slds-hide">
<span class="slds-pill">
<span class="slds-pill__label">
{!v.selectedRecord.Name}
</span>
<span class="slds-button slds-button--icon slds-pill__remove deleteIcon" onclick="{!c.clear}">
<c:LC_svg class="slds-button__icon" xlinkHref="{!$Resource.SLDS092 + '/assets/icons/utility-sprite/svg/symbols.svg#close'}" />
<span class="slds-assistive-text">Remove</span>
</span>
</span>
</div>
<div aura:id="lookupField" class="slds-show">
<ui:inputText updateOn="keyup" keyup="{!c.keyPressController}" aura:id="LookupGeneral"
class="slds-lookup__search-input slds-input "
value="{!v.SearchKeyWord}" placeholder="search.." />
</div>
</div>
</div>
<!--This part is for Display typehead lookup result List-->
<div class="slds-lookup__menu slds" id="lookup-348">
<div class="slds-lookup__item--label slds-text-body--small">{!v.Message}</div>
<center> <ui:spinner aura:id="spinner"/> </center>
<ul class="slds-lookup__list" role="listbox">
<aura:iteration items="{!v.listOfSearchRecords}" var="singleRec">
<c:CustomLookupResult Obj="{!singleRec}" />
</aura:iteration>
</ul>
</div>
</div>
</div>
</aura:component>
CustomLookupController.js:
({
keyPressController : function(component, event, helper) {
// get the search Input keyword
var getInputkeyWord = component.get("v.SearchKeyWord");
var getObjName = component.get("v.ObjName");
var getRecordCount = component.get("v.RecordCount");
// 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, getObjName, getRecordCount);
}
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 pillTarget = component.find("lookup-pill");
var lookUpTarget = component.find("lookupField");
$A.util.addClass(pillTarget, 'slds-hide');
$A.util.removeClass(pillTarget, 'slds-show');
$A.util.addClass(lookUpTarget, 'slds-show');
$A.util.removeClass(lookUpTarget, 'slds-hide');
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) {
// get the selected Account record from the COMPONETN event
var selectedRecordGetFromEvent = event.getParam("RecordByEvent");
var RecordSelected = component.getEvent("RecordSelected");
RecordSelected.setParams({
SelectedValue: selectedRecordGetFromEvent.Id
}).fire();
component.set("v.selectedRecord" , selectedRecordGetFromEvent);
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');
var lookUpTarget = component.find("lookupField");
$A.util.addClass(lookUpTarget, 'slds-hide');
$A.util.removeClass(lookUpTarget, 'slds-show');
},
// automatically call when the component is done waiting for a response to a server request.
hideSpinner : function (component, event, helper) {
var spinner = component.find('spinner');
var evt = spinner.get("e.toggle");
evt.setParams({ isVisible : false });
evt.fire();
},
// automatically call when the component is waiting for a response to a server request.
showSpinner : function (component, event, helper) {
var spinner = component.find('spinner');
var evt = spinner.get("e.toggle");
evt.setParams({ isVisible : true });
evt.fire();
},
})
CustomLookupHelper.js
-----------------------------------
({
searchHelper : function(component,event,getInputkeyWord, getObjName, getRecordCount) {
// call the apex class method
var action = component.get("c.fetchRecords");
// set param to method
action.setParams({
'searchKeyWord': getInputkeyWord,
'ObjName' : getObjName,
'count' : getRecordCount
});
// set a callBack
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var storeResponse = response.getReturnValue();
// if storeResponse size is equal 0 ,display No Result Found... message on screen.
if (storeResponse.length == 0) {
component.set("v.Message", 'No Result Found...');
} else {
component.set("v.Message", 'Search Result...');
}
// set searchResult list with return value from server.
component.set("v.listOfSearchRecords", storeResponse);
}
});
// enqueue the Action
$A.enqueueAction(action);
},
})
Custom Lookup Example: (Usage):
CustomLookupExample.cmp:
---------------------------------------
<aura:component controller="ContactSavecls">
<aura:attribute name="contactObj" type="Contact" default="{'sobjectType':'Contact',
'AccountId':'','FirstName':'',
'LastName':''}"/>
<div>
<div class="slds-form-element__control">
<ui:inputText class="slds-input" label="Last Name" value="{!v.contactObj.LastName}"/>
<c:CustomLookup ObjName="Account" FieldLabel="Related Account"
RecordCount="5"
RecordSelected="{!c.handleRecordSelection}" />
</div>
<ui:button press="{!c.contactSave}">Save Contact</ui:button>
</div>
</aura:component>
CustomLookupExample.js:
-------------------------------------
({
handleRecordSelection : function(component, event, helper) {
alert('hi'+event.getParam("SelectedValue"));
component.set("v.contactObj.AccountId", event.getParam("SelectedValue"));
},
contactSave:function(component, event, helper){
var action = component.get("c.saveContact");
var contRec = component.get("v.contactObj");
action.setParams({"contObj":contRec});
action.setCallback(this,function(data){
var result = data.getReturnValue();
alert(result);
});
$A.enqueueAction(action);
}
})
ApexController:
--------------------
public class ContactSavecls{
@Auraenabled
public static String saveContact(Contact contObj){
insert contObj;
return contObj.Id;
}
}
output:
------------
References:
------------------
https://developer.salesforce.com/blogs/developer-relations/2015/06/salesforce-lightning-inputlookup-missing-component.html
http://sfdcmonkey.com/2017/07/17/re-usable-custom-lookup/
http://sfdcmonkey.com/2017/01/07/custom-lookup-lightning-component/
https://teamforcesite.wordpress.com/2017/09/20/how-to-build-custom-lookup-in-lightning/
https://github.com/enreeco/inputlookup
https://www.jitendrazaa.com/blog/salesforce/lookup-component-in-salesforce-lightning/
https://www.lightningdesignsystem.com/components/lookups/