• Reusable Custom LWC Lookup Component

    Published By: salesforcepoint
    Published: Thursday, 9 July 2020
    A- A+

    How to use Lookup in Lightning web components: 

    Lookup Component In Lightning Web Components

    LWC Lookup Component :

    In this post we are going to see how to create/use lookup field in lwc input forms. Unlike other fields we don't have predefined tag for lookup field in LWC, if you want to achieve lookup functionality in lightning web components we need to write our own code. 

    Note: By using lightning-record-edit-form we can achieve lookup functionality, but that may not be helpful if we need to pre-populate value in the lookup field and need to show records based on filter conditions. But custom code supports all the functionalities based on our customization. 

    Custom LWC Lookup component code


    1. Create Apex class: LwcLookupController
     public class LwcLookupController {  
       @AuraEnabled(cacheable=true)  
       public static List<sobject> findRecords(String searchKey, String objectName) {  
         string searchText = '\'' + String.escapeSingleQuotes(searchKey) + '%\'';  
         string query = 'SELECT Id, Name FROM ' +objectName+ ' WHERE Name LIKE '+searchText+' LIMIT 6';  
         return Database.query('SELECT Id, Name FROM ' +objectName+ ' WHERE Name LIKE '+searchText+' LIMIT 6');  
       }  
     }  
    

    2. Create new Lightning web component: lwcLookup

    lwcLookup.js
     import { LightningElement, track, wire, api } from "lwc";  
     import findRecords from "@salesforce/apex/LwcLookupController.findRecords";  
     export default class LwcLookup extends LightningElement {  
      @track recordsList;  
      @track searchKey = "";  
      @api selectedValue;  
      @api selectedRecordId;  
      @api objectApiName;  
      @api iconName;  
      @api lookupLabel;  
      @track message;  
        
      onLeave(event) {  
       setTimeout(() => {  
        this.searchKey = "";  
        this.recordsList = null;  
       }, 300);  
      }  
        
      onRecordSelection(event) {  
       this.selectedRecordId = event.target.dataset.key;  
       this.selectedValue = event.target.dataset.name;  
       this.searchKey = "";  
       this.onSeletedRecordUpdate();  
      }  
       
      handleKeyChange(event) {  
       const searchKey = event.target.value;  
       this.searchKey = searchKey;  
       this.getLookupResult();  
      }  
       
      removeRecordOnLookup(event) {  
       this.searchKey = "";  
       this.selectedValue = null;  
       this.selectedRecordId = null;  
       this.recordsList = null;  
       this.onSeletedRecordUpdate();  
     }  
       
    
    
    
      getLookupResult() {  
       findRecords({ searchKey: this.searchKey, objectName : this.objectApiName })  
        .then((result) => {  
         if (result.length===0) {  
           this.recordsList = [];  
           this.message = "No Records Found";  
          } else {  
           this.recordsList = result;  
           this.message = "";  
          }  
          this.error = undefined;  
        })  
        .catch((error) => {  
         this.error = error;  
         this.recordsList = undefined;  
        });  
      }  
       
      onSeletedRecordUpdate(){  
       const passEventr = new CustomEvent('recordselection', {  
         detail: { selectedRecordId: this.selectedRecordId, selectedValue: this.selectedValue }  
        });  
        this.dispatchEvent(passEventr);  
      }  
     }  
    

    lwcLookup.html
     <template>  
       <div class="slds-form-element">  
         <label class="slds-form-element__label" for="combobox-id-2">{lookupLabel}</label>  
         <div class="slds-form-element__control">  
           <div class="slds-combobox_container">  
             <div class="slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open" aria-expanded="true" aria-haspopup="listbox" role="combobox">  
               <template if:true={selectedValue}>  
               <div data-key="pilldiv" class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_left-right" role="none">  
                 <span class="slds-icon_container slds-icon-standard-account slds-combobox__input-entity-icon" title="object">  
                  <div class="slds-icon slds-icon_small" aria-hidden="true">  
                   <lightning-icon icon-name={iconName} size="small"></lightning-icon>  
                  </div>  
                  <span class="slds-assistive-text">Record</span>  
                 </span>  
                 <input type="text" class="slds-input slds-combobox__input slds-combobox__input-value" id="combobox-id-5" aria-controls="listbox-id-5" role="textbox" placeholder="Select an Option" readonly value={selectedValue} />  
                 <button class="slds-button slds-button_icon slds-input__icon slds-input__icon_right" onclick={removeRecordOnLookup}  
                 title="Remove selected option">  
                  <span class="slds-button__icon" aria-hidden="true" >  
                   <lightning-icon icon-name="utility:close"   
                    size="xx-Small" class="slds-icon slds-icon slds-icon_x-small slds-icon-text-default" aria-hidden="true"></lightning-icon>  
                  </span>  
                  <span class="slds-assistive-text">Remove selected record</span>  
                 </button>  
                </div>  
               </template>  
       
               <template if:false={selectedValue}>  
               <div data-key="searchdiv" class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right" role="none">  
                 <input type="text" onfocusout={onLeave} value={searchKey} onkeyup={handleKeyChange} onchange={handleKeyChange} class="slds-input slds-combobox__input slds-has-focus" id="combobox-id-2" aria-autocomplete="list" aria-controls="listbox-id-2" role="textbox" placeholder="Search..." />  
                 <span class="slds-icon_container slds-icon-utility-search slds-input__icon slds-input__icon_right">  
                   <lightning-icon icon-name="utility:search" size="xx-Small" class="slds-icon slds-icon slds-icon_x-small slds-icon-text-default" aria-hidden="true"></lightning-icon>  
                 </span>  
               </div>  
       
               <template if:true={recordsList}>  
               <div id="listbox-id-2-venu" data-key="dropdownresult" class="slds-show slds-dropdown slds-dropdown_length-with-icon-7 slds-dropdown_fluid" role="listbox">  
                 <ul class="slds-listbox slds-listbox_vertical" role="presentation" >  
                   <template if:true={message}>  
                   <center> {message}</center>  
                   </template>  
                   <template for:each={recordsList} for:item="record">  
                     <li id={record.Id} key={record.Id} onclick={onRecordSelection} role="presentation" class="slds-listbox__item">  
                     <div data-key={record.Id} data-name={record.Name} class="slds-media slds-listbox__option slds-listbox__option_entity slds-listbox__option_has-meta" role="option">  
                       <span class="slds-media__figure slds-listbox__option-icon">  
                         <span class="slds-icon_container">  
                           <lightning-icon icon-name={iconName} size="small"></lightning-icon>  
                         </span>  
                       </span>  
                       <span class="slds-media__body">  
                         <span data-key={record.Id} data-name={record.Name} class="slds-listbox__option-text slds-listbox__option-text_entity">{record.Name} </span>  
                       </span>  
                     </div>  
                   </li>  
                   </template>  
                 </ul>  
               </div>  
               </template>  
               </template>  
             </div>  
           </div>  
         </div>  
       </div>  
     </template>  
    

    Now we are done with lookup component creation. Let's see how to use it in another Lightning web component.

    Important public properties we need to pass to lookup component.




    1. objectApiName (object-api-name) : Which object records we are going to fetch on lookup. This is required property.
    2. iconName (icon-name) : This is used to show object specific icon in lookup list and selected record.
    3. selectedRecordId (selected-record-id ): If we need to pre populate selected record on load, then we need to assign record id which we should show on lookup.
    4. selectedValue (selected-value ): Pre Selected record name.

    Important event we need to handle on parent Lwc component:

    onrecordselection: This event gets fired every time when new record selected or selected record removed on lookup. By using this event we can get the selected record id
    (event.detail.selectedRecordId) and name (event.detail.selectedValue) values. check below example code.

    3. Create Demo Lightning web component: lwcLookupDemo
    This component is used for checking output of lookup component. In below example we are fetching lookup records from Account object and we are handling onrecordselection event on "onAccountSelection" functtion.

    lwcLookupDemo.js
     import { LightningElement, track } from 'lwc';  
     export default class LwcLookupDemo extends LightningElement {  
       @track accountName;  
       @track accountRecordId;  
    
       onAccountSelection(event){  
       this.accountName = event.detail.selectedValue;  
       this.accountRecordId = event.detail.selectedRecordId;  
       }  
     }  
    

    lwcLookupDemo.html
     <template>  
       <div class="slds-box">  
         <c-lwc-lookup lookup-label="Account" object-api-name="account" icon-name="standard:account"  
           onrecordselection={onAccountSelection}></c-lwc-lookup>  
       </div>  
       <div class="slds-box">  
         Selected Account Name : {accountName}  
         Selected Account Id  : {accountRecordId}  
       </div>  
     </template>  
    

    4. Add component to App builder page: Add this demo lwc component to app builder page to see output of Lookup.

    LWC Lookup component output

    Check how to use this LWC lookup component in Lightning Aura Component
  • No Comment to " Reusable Custom LWC Lookup Component "