How to create custom reusable lookup field in LWC? Lets figure out.
Component Bundles:
- lookupFieldComponentLWC (Parent Comp)
- lookupResultComponentLWC (Child Comp)
- ObjectManager (Apex Class)
** components are created as a part of proof of concept. it can be modified and optimized as per requirement.**
References:
- https://developer.salesforce.com/docs/component-library/bundle/lightning-input/example
- https://www.sfdcpanther.com/custom-reusable-lookup-in-lwc/
Demo:
Code:
lookupFieldComponentLWC.html
<template>
<lightning-card title="Custom Reusable Lookup Field">
<lightning-layout>
<lightning-layout-item>
<template if:false={selectedValue}>
<lightning-input type="text" placeholder="Input text.." onchange={inputTextHandler}></lightning-input>
<template if:true={searchKey}>
<template if:true={allRecords}>
<template for:each={allRecords} for:item= "record">
<c-lookup-result-component-l-w-c key={record.Id} record={record} icon-name={iconName} onselect={handleSelect}></c-lookup-result-component-l-w-c>
</template>
</template>
</template>
</template>
<template if:true={selectedValue}>
<div 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="Account">
<lightning-icon icon-name={iconName} ></lightning-icon>
</span>
<input class="slds-input slds-combobox__input
slds-combobox__input-value"
id="combobox-id-5" aria-controls="listbox-id-5"
autocomplete="off" role="textbox" type="text"
placeholder="Select an Option" readonly=""
value={selectedValue.Name}
disabled
/>
<button class="sicon_container slds-button slds-button_icon
slds-input__icon slds-input__icon_right"
title="Remove selected option"
onclick={handleRemove}>
<lightning-icon icon-name="utility:close" size="small">
</lightning-icon>
<span class="slds-assistive-text">Remove selected option</span>
</button>
</div>
</template>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
</template>
--------------------------------------------------------------------------------------------------------------------------
lookupFieldComponentLWC.js
import { LightningElement, api, track } from 'lwc';
import getAllRecords from '@salesforce/apex/ObjectManager.getRecords';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class LookupFieldComponentLWC extends LightningElement {
@track searchKey;
@track allRecords = [];
@track recordId;
@track selectedValue;
@api objectName = 'Account'; //to reuse for other object change the object here
@api iconName = 'standard:account'; //use the respective object icon
@api searchField= 'Name'; // use the field for search
inputTextHandler(event){
this.searchKey= event.detail.value;
console.log('searchKey>>'+this.searchKey);
if(this.searchKey){
this.getRecords();
}
}
getRecords(){
getAllRecords({searchKey : this.searchKey, objectName : this.objectName, searchField : this.searchField}).then((allRecords) =>{
this.allRecords = allRecords;
console.log('allRecords>>>'+this.allRecords[0]);
for(let i=0;i<this.allRecords.length;i++){
const rec = this.allRecords[i];
this.allRecords[i].Name= rec[this.searchField];
}
}).catch((error)=>{
this.showToast('ERROR',error.body.message, 'error');
})
}
handleSelect(event){
this.recordId = event.detail; //selected recordId
this.selectedValue = this.allRecords.find(record=> record.Id === this.recordId); //selected record
console.log('this.recordId>>>'+this.recordId);
}
handleRemove(){
this.selectedValue = undefined;
this.allRecords = undefined;
}
showToast(title, message, variant) {
const evt = new ShowToastEvent({
title: title,
message: message,
variant: variant,
});
this.dispatchEvent(evt);
}
}
--------------------------------------------------------------------------------------------------------------------------
lookupResultComponentLWC.html
<template>
<div >
<div class="slds-grid slds-wrap
slds-dropdown_length-with-icon-7
slds-dropdown_fluid
slds-p-left_small">
<div class="slds-col slds-size_4-of-4 ">
<ul class="slds-listbox slds-listbox_vertical" role="presentation">
<li role="presentation" class="slds-listbox__item">
<div class="slds-media slds-listbox__option
slds-listbox__option_entity
slds-listbox__option_has-meta"
role="option"
onclick={handleSelect}>
<span class="slds-media__figure slds-listbox__option-icon">
<lightning-icon icon-name={iconName} size="small"></lightning-icon>
</span>
<span class="slds-media__body"
style="padding-top: 9px;font-weight: 600;">
<span class="slds-listbox__option-text slds-listbox__option-text_entity">
{record.Name}
</span>
</span>
</div>
</li>
</ul>
</div>
</div>
</div>
</template>
--------------------------------------------------------------------------------------------------------------------------
lookupResultComponentLWC.js
import { LightningElement, api } from 'lwc';
export default class LookupResultComponentLWC extends LightningElement {
@api record;
@api iconName;
handleSelect(event){
event.preventDefault();
const selectedRow = new CustomEvent('select',{detail : this.record.Id});
this.dispatchEvent(selectedRow);
}
}
--------------------------------------------------------------------------------------------------------------------------
ObjectManager.cls
public with sharing class ObjectManager {
@AuraEnabled
public static List<SObject> getRecords(String searchKey, String objectName, String searchField){
String key = '%' + searchKey + '%';
String QUERY = 'Select Id, '+searchField+' From '+objectName +' Where '+searchField +' LIKE :key';
System.debug(System.LoggingLevel.DEBUG, QUERY);
List<SObject> sObjectList = Database.query(QUERY);
return sObjectList;
}
}