custom Lookup

How to create custom Lookup in lightning component

Lightning Component

This Post Is Outdated Due To Some Salesforce New Release update, Please refer below post for reusable custom lightning component
thanks

Create Re-Usable Custom Lookup In Salesforce Lightning Component Version 2 : Dynamic

Prerequisites : basic understanding of Lightning Component.

custom Lookup

 

custom Lookup resources

 

Step 0 : Create Support SVG Lightning component.

In the first step, we are create a small lightning component, for rendered the SVG icons in our Lookup component.

you can also use this svg component in any of your lightning component for display the SVG icons

  • create a new lightning component bundle with Name svg
lightning component [svg.cmp]
<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#download" />
    <aura:attribute name="aria-hidden" type="String" default="true" description="aria-hidden true or false. defaults to true" />
</aura:component>
next click on the RENDERER tab on lightning component bundle and past below code:

renderer tab

RENDERER.js  [svgRenderer.js]
({
	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;
	}
})

Yoo… our SVG component is ready for Use… 🙂

now we can display SVG icons from our Design System Zip file (static resources) By using.

<c:svg class="slds-input__icon slds-show" xlinkHref="{!$Resource.SLDS24 + '/assets/icons/utility-sprite/svg/symbols.svg#search'}" />
<!-- here c: is org. namespace prefix-->

Lightning Icon Reference :https://www.lightningdesignsystem.com/icons/

Step 1 : Create Apex Class Controller.
Apex class [lookUpController.apxc]
public class lookUpController {
   @AuraEnabled
 public static List < account > fetchAccount(String searchKeyWord) {
  String searchKey = searchKeyWord + '%';
  List < Account > returnList = new List < Account > ();
  List < Account > lstOfAccount = [select id, Name from account where Name LIKE: searchKey];
 
  for (Account acc: lstOfAccount) {
     returnList.add(acc);
     }
  return returnList;
 }
}
  • In above Apex class we have only one @AuraEnabled Method.
  • In this method we have one String ‘searchKeyWord’ parameter.
  • By this parameter we are find Account record  List and Return the list.
 Step 2 : Create Lightning Event
  • Next we create a Lightning Event bundle for communicate data(attribute values) between different components.
  • Events are contain attributes that can be set before the event is fired and read when the event is handled by component.
lightning Event [selectedAccountEvent.evt]
<aura:event type="COMPONENT" description="by this event we are pass the selected account in the parent component">
    <aura:attribute name="accountByEvent" type="account"/>
</aura:event>
  •  In above Event we have only single attribute which type is Account type.
  • by this attribute, we are passing the selected account record to parent component [ customLookup ]  by child component[customLookupResult ].
COMPONENT BLUEPRINT :

custom Lookup blueprint

Step 3 : Create Child Component For Display the Search Result List
Lightning Component [customLookupResult.cmp]
<aura:component >
    <aura:attribute name="oAccount" type="Account" />
  <!--Register the component level event-->
    <aura:registerEvent name="oSelectedAccountEvent" type="c:selectedAccountEvent"/>
    
    <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:svg class="slds-input__icon" xlinkHref="{!$Resource.SLDS24 + '/assets/icons/standard-sprite/svg/symbols.svg#account'}" />                   
            <div class="slds-lookup__result-text"><a onclick="{!c.selectAccount}">{!v.oAccount.Name}</a></div>
          </div>
        </div>    
        </span>
    </li>
</aura:component>
JS Controller [customLookupResultController.js]
({
	 selectAccount : function(component, event, helper){      
    // get the selected Account from list  
      var getSelectAccount = component.get("v.oAccount");
    // call the event   
      var compEvent = component.getEvent("oSelectedAccountEvent");
    // set the Selected Account to the event attribute.  
         compEvent.setParams({"accountByEvent" : getSelectAccount });  
    // fire the event  
         compEvent.fire();
    },
})
NOTE: Change $Resource.SLDS24 with your SLDS file Name (static resource zip file Name).
Step 4 : Create Lightning Custom Lookup Component
  • Create a lightning component bundle with Name customLookup
lightning component [customLookup.cmp]
<aura:component controller="lookUpController" >
   <!---Use Salesforce Lightning Design System CSS From Static resources-->   
   <ltng:require styles="{!$Resource.SLDS24 + '/assets/styles/salesforce-lightning-design-system.css'}"/>
   
    <!--declare attributes--> 
   <aura:attribute name="selectedRecord" type="Account" default="{}" description="Use,for store SELECTED sObject Record"/>
   <aura:attribute name="listOfSearchRecords" type="Account[]" description="Use,for store the list of search records which returns from apex class"/>
   <aura:attribute name="SearchKeyWord" type="string"/>
   <aura:attribute name="Message" type="String" default="Search Result.."/>
    
   <!--declare events hendlers-->  
   <aura:handler name="oSelectedAccountEvent" event="c:selectedAccountEvent" action="{!c.handleComponentEvent}"/>
   <aura:handler event="aura:waiting" action="{!c.showSpinner}"/>
   <aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/>
 
   <!-- https://www.lightningdesignsystem.com/components/lookups/ --> 
   <div class="slds-m-around--large">
      <div aura:id="searchRes" class="slds-form-element slds-lookup slds-is-close" data-select="single">
         <label class="slds-form-element__label" for="lookup-348"> Account Name </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">
               <c:svg class="slds-input__icon slds-show" xlinkHref="{!$Resource.SLDS24 + '/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>
                     <button class="slds-button slds-button--icon slds-pill__remove" onclick="{!c.clear}">
                        <c:svg class="slds-button__icon" xlinkHref="{!$Resource.SLDS24 + '/assets/icons/utility-sprite/svg/symbols.svg#close'}" />
                        <span class="slds-assistive-text">Remove</span>
                     </button>
                  </span>
               </div>
              <div aura:id="lookupField" class="slds-show">
               <ui:inputText  updateOn="keyup" keyup="{!c.keyPressController}" 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 oAccount="{!singleRec}" />
               </aura:iteration>
            </ul>
         </div>
      </div>
   </div>
</aura:component>
JS Controller [customLookupController.js]
({
  
	keyPressController : function(component, event, helper) {
      // 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 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 selectedAccountGetFromEvent = event.getParam("accountByEvent");
	   
	   component.set("v.selectedRecord" , selectedAccountGetFromEvent); 
       
        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();    
    },
    
})
JS Helper [customLookupHelper.js]
({
	searchHelper : function(component,event,getInputkeyWord) {
	  // call the apex class method 
     var action = component.get("c.fetchAccount");
      // set param to method  
        action.setParams({
            'searchKeyWord': getInputkeyWord
          });
      // 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);
    
	},
})
TestApp.app
<aura:application >
  <c:customLookup/>
 <!-- here c: is org. namespace prefix-->
</aura:application>

Output :

custom Lookup
Related Resources :

Salesforce Lightning Design System Lookup

Lightning Component Events

ui:Spinner

Like our facebook page for new post updates.? & Don’t forget to bookmark this site for your future reference.

if you have any suggestions or issue with it, you can post in comment box. ?

49 comments

  • Hi –
    I’m getting the following exception: System.FinalException: Cannot modify a collection while it is being iterated.

    Can you help me in adressing this issue.

    Thanks in advance.

    Best Regards
    Rajesh

    • HI @Rajesh
      did you get this error with above apex class (Apex class [lookUpController.apxc]), which use in this sample lookup code , ?
      and Basically This type exception is occurred when you are trying to modify some record while you are iterating same record.

      you can post you issue on http://sfdcmonkey.com/community/main-forum/
      in Details.so i look into this.
      thanks

      • Hi-
        Thanks for the quick reply. It was able to figure this out. I modified your code and did that above mistake. I has another issue regarding the performance so i posted in the forum.

        Thanks in advance.

  • I have created a custom lookup component on account object in my results I want to specify the record type. based upon record type only I need display the results in search field. Please tell me how can I.

     

    Thanks & Best Regards,

    Rajesh

    • Hi Rajesh, you can add a where condition in your component apex controller query such as “WHERE RecordType.Name = ‘yourSpecificRecordTypeName'”
      Thanks

  • Hello. Much thanks for this article. But I have a remark: in summer 17 they removed ‘display:flex;’ from selector “.slds-lookup[data-select=single] .slds-pill, .slds-lookup[data-select=multi] .slds-pill {“, so now when record is selected, it does not stretch to fit parent container. Can you make proper adjustments please?

    • hi Vladyslav Kushney,
      Thanks for your feedback, and i don’t have Summer 17 ready org [sandbox] right now for testing it. so i will update soon when i have access in summer 17 ready org.
      and can you please mention the official doc. on this new update
      thanks

  • Is n’t it possible in other ways without creating components for lookup field? Can’t we use Force input field and what other ways to get lookup field ?

    • HI SF User ,
      Thanks for your valuable feedback :).
      you can get selected value in client side(javaScript) controller by :

      component.get(“v.selectedRecord”) // for selected account object
      component.get(“v.selectedRecord”).Name // for selected account Name
      component.get(“v.selectedRecord”).Id // for selected account Id
      Hopes it helps you 🙂
      thanks

  • Thank you for the quick reply, but I was not specific enough.

    I wanted to know, how can we get the selected record (Account) into the APEX controller?

     

    Thank you

    • ok, so first create a simple button in your lightning component

      button onclick=”{!c.onSave}”> save button

      now create onSave javaScript controller function
      onSave : function (component, event, helper) {
      // call the apex class method
      var action = component.get(“c.saveAccount”);
      // set param to method
      action.setParams({
      ‘obj’: component.get(“v.selectedRecord”)
      });
      // set a callBack
      action.setCallback(this, function(response) {
      var state = response.getState();
      if (state === “SUCCESS”) {
      console.log(state);
      }
      });
      // enqueue the Action
      $A.enqueueAction(action);
      }

      add method in apex class
      @AuraEnabled
      public static void saveAccount(Account obj){
      system.debug(‘selectedAccount–>’ + obj);
      }

      Hops it helps you
      thanks

  • First of all this is a great component, thanks for sharing it.

    I would like to use this with another component like this :

    Parent Component

    >>>>>Lookup Component

    Is there a way to set the default value as a parameter so when the component is rendered he already has a value on it? (Like a account select or so)

    Thanks!

  • Hi,

    Thanks for such a wonderful article!

    I have one question, when i select an account from the list then it doesn’t get in to the search box, can you please help on this.

    Thanks.

  • great article. The big icons appears on page load at once and than disappears. what is wrong?

    • Hi nothing is wrong here, sometime it will take little bit time to load lightning css i guess.

  • Hi! excellent article! I wonder how I can reset the selection, I want to clear the form after submission if success but I cant find a way to clear the selection, I tried setting selectedRecord to null and selection is cleared, but I see the empty square with the X.
    Thanks!

  • Thank you for the Article.It really helped me.
    One problem that i faced while using your article was that search and cancel symbols not showing in IE 11 where as its showing correctly in Chrome Version 59.0.3071.115.Please help me on this

    Thank you

  • While trying to fetch the selectedAccount parameter from the event, the function is returning undefined, hence although search is being done, while trying to save it the name of the selectedRecord does not appear. Am i missing something here? I saw that the event is registered

  • HI sfdcMonkey,

    I am using lookup field . and want to show error if that field is blank . I am using another component to show the lookup field value. I am show error another fields but not successs to show blank error on the lookup field . pls guide how to show error on lookup field.

    thanks

    vikas

     

  • Hi SFDC Monkey,

    Excellent article..,if i want to display header Name in the look up display list, can you help me in achieving this?.

    Thanks,

    Jewelslyn

  • Great article!

    I was just wondering if  we can add multiple accounts through the search and display the selection as lightning pills? I see its working for only one selection.

  • Hi,

    I have created the aura component with quick action. Here i need to pre-populate lookup value based on current record for using custom lookup. Please help me how we can populate the default value from source record look up field here.

  • Nice article, Can you help me on 1) how to make this multi select? 2) dependent lookup’s i.e., on selecting value in one lookup other lookup field values should vary?

     

    Thanks

    Hemanth

     

     

  • Thank you so much for this!  I was at my wits end creating sub-flows for lookup field replacements in my VisualWorkflows.

    I used your code above and then created a lightning component which uses the customlookup.

    CMP:

    <aura:component implements=”lightning:availableForFlowScreens” access=”global”>
    <aura:attribute name=”selectedRecord” type=”Contact” default=”{}”/>

    <div class=”slds-m-around_large”>

    <c:customLookup objectAPIName=”contact” IconName=”standard:contact” label=”Contact” selectedRecord=”{!v.selectedRecord}” />
    </div>

    </aura:component>

    And a Design for the SelectedRecord attribute.

    Now i need to figure out how to limit the look up to contacts in a specific Account.

    • Ok.. i figured out how to add a limit by a record for the use in my Flow.

      I had to modify the base code you provided with a simple if statement, variables for the limitfield, limitvalue, Operator, ANDOR, and one boolean variable to use or not use the limit the additional Statement or not.

      So my flow now passes in values for either the 4 fields used to build the added string to the sQuery.

      Thank you so much again for the starting point!

  • I have used same component to display custom flookup its working perfect but i need to save the lookup value corresponding to other value such as name, phone value etc it getting saved in the back end, in the component only lookup field gets empty. how can i resolve this issue.

  • Hi my requirement is when i click on the lookup search it  will open a window displaying all the accounts and need one button if user wants to create a account please help me out thanks advance.

     

     

  • I want to select the lookup filed value by using keyboard up and down keys.please give me the answer

  • I have copy pasted the whole code just to understand how the flow works.
    however, I have received the following error:

    “This page has an error. You might just need to refresh it. Action failed: ltng:outApp$controller$init [Incorrect usage of ltng:outApp. Refer to the ‘Lightning Components Developer Guide’ for correct usage] Failing descriptor: {ltng:outApp$controller$init}”

    Help me out with this

  • how to implement search record add one by one for e.g standard email functionality when we search Email id we can add multiple Email Id i need to implement same how can possible. any one help me

  • when I start writing her self blocks me and shows me this error message
    Sorry to interrupt
    This page has an error. You might just need to refresh it.
    Unable to find action ‘hideSpinner’ on the controller of c:customLookup
    Failing descriptor: {c:customLookup}

  • Hi ,
    You mentioned this component will not work due to some release update. I used this component and It was working before the spring 19 release but suddenly it is giving “<strong>Uncaught render threw an error in ‘c:iCRM_LookUpSVG_LT’ [Failed to execute ‘querySelector’ on ‘Element’: ‘#httpsgauk–ghservdev.lightning.force.comlightningoAsset%7B’iconsutility-spritesvgsymbols.svg_search’}’ is not a valid selector.]</strong>” error on component load only.

    Will you please help me in this. I’m just curios what actually changed. In your new updated component I’m not able to see “SVG” component. So there any reason you removed it?

    It’s very critical issue for me, Already deployed this in production so have to fix it ASAP.

    Thanks in advance.

Leave a Reply