In Salesforce, we use lookup field to connect objects. We can use inputField to show them but sometimes we need our own custom lookup with custom filter. Previously I have created Lookup component in Lightning which you can check here. So today I made that Lightning Web Components (LWC) compatible, and made a Custom Lookup in Lightning Web Components (LWC).
This is how our output will look using Lightning Web Component. UI is similar in both Lightning and Lightning Web Component.

So we will now check the code part.
lwcCustomLookup.html
<template>
<lightning-card>
<h3 slot="title">
<lightning-icon icon-name="utility:connected_apps" size="small"></lightning-icon>
Custom Lookup in Lightning Web Components
</h3>
<div slot="footer">
</div>
<div>
<div class="slds-form-element">
<div class="slds-form-element__control">
<div class="slds-combobox_container">
<div class={txtclassname} data-id="resultBox" aria-expanded="false" aria-haspopup="listbox" role="combobox">
<div class="slds-form-element__control slds-input-has-icon slds-input-has-icon slds-input-has-icon_left-right" role="none">
<div>
<span class="slds-icon_container slds-icon-utility-search slds-input__icon iconheight">
<lightning-icon class="slds-icon slds-icon slds-icon_small slds-icon-text-default" icon-name={iconName} size="x-small" alternative-text="icon" ></lightning-icon>
</span>
</div>
<lightning-input required={required} read-only={inputReadOnly} data-id="userinput" label={Label} name="searchText" onchange={searchField} value={selectRecordName} class="leftspace"></lightning-input>
<div if:true={iconFlag}>
<span class="slds-icon_container slds-icon-utility-search slds-input__icon slds-input__icon_right iconheight">
<lightning-icon class="slds-icon slds-icon slds-icon_small slds-icon-text-default" icon-name="utility:search" size="x-small" alternative-text="icon" ></lightning-icon>
</span>
</div>
<div if:true={clearIconFlag}>
<button class="slds-input__icon slds-input__icon_right slds-button slds-button_icon iconheight" onclick={resetData}>
<lightning-icon class="slds-icon slds-icon slds-icon_small slds-icon-text-default" icon-name="utility:clear" size="x-small" alternative-text="icon" ></lightning-icon>
<span class="slds-assistive-text">Clear</span></button>
</div>
</div>
<!-- Second part display result -->
<div id="listbox-id-1" class="slds-dropdown slds-dropdown_length-with-icon-7 slds-dropdown_fluid" role="listbox">
<ul class="slds-listbox slds-listbox_vertical" role="presentation">
<template for:each={searchRecords} for:item="serecord">
<li role="presentation" class="slds-listbox__item" key={serecord.recId}>
<div data-id={serecord.recId} data-name={serecord.recName} onclick={setSelectedRecord} 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 slds-icon-standard-account">
<lightning-icon icon-name={iconName} class="slds-icon slds-icon slds-icon_small slds-icon-text-default" size="x-small"></lightning-icon>
</span>
</span>
<span class="slds-media__body">
<span class="slds-listbox__option-text slds-listbox__option-text_entity">{serecord.recName}</span>
<span class="slds-listbox__option-meta slds-listbox__option-meta_entity">{objectName} • {serecord.recName}</span>
</span>
</div>
</li>
</template>
</ul>
</div>
<div if:true={messageFlag}>
No result found.
</div>
<div if:true={LoadingText}>
Loading...
</div>
</div>
</div>
</div>
</div>
</div>
</lightning-card>
</template>
lwcCustomLookup.js
import { LightningElement,wire,api,track } from 'lwc';
import getResults from '@salesforce/apex/lwcCustomLookupController.getResults';
export default class LwcCustomLookup extends LightningElement {
@api objectName = 'Account';
@api fieldName = 'Name';
@api selectRecordId = '';
@api selectRecordName;
@api Label;
@api searchRecords = [];
@api required = false;
@api iconName = 'action:new_account'
@api LoadingText = false;
@track txtclassname = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';
@track messageFlag = false;
@track iconFlag = true;
@track clearIconFlag = false;
@track inputReadOnly = false;
searchField(event) {
var currentText = event.target.value;
this.LoadingText = true;
getResults({ ObjectName: this.objectName, fieldName: this.fieldName, value: currentText })
.then(result => {
this.searchRecords= result;
this.LoadingText = false;
this.txtclassname = result.length > 0 ? 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open' : 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';
if(currentText.length > 0 && result.length == 0) {
this.messageFlag = true;
}
else {
this.messageFlag = false;
}
if(this.selectRecordId != null && this.selectRecordId.length > 0) {
this.iconFlag = false;
this.clearIconFlag = true;
}
else {
this.iconFlag = true;
this.clearIconFlag = false;
}
})
.catch(error => {
console.log('-------error-------------'+error);
console.log(error);
});
}
setSelectedRecord(event) {
var currentRecId = event.currentTarget.dataset.id;
var selectName = event.currentTarget.dataset.name;
this.txtclassname = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';
this.iconFlag = false;
this.clearIconFlag = true;
this.selectRecordName = event.currentTarget.dataset.name;
this.selectRecordId = currentRecId;
this.inputReadOnly = true;
const selectedEvent = new CustomEvent('selected', { detail: {selectName, currentRecId}, });
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
resetData(event) {
this.selectRecordName = "";
this.selectRecordId = "";
this.inputReadOnly = false;
this.iconFlag = true;
this.clearIconFlag = false;
}
}
lwcCustomLookup.css
div input[readonly] {
padding-left: 1.75rem !important;
}
.slds-input{
padding-left: 1.75rem !important;
}
.slds-input-has-icon .slds-input__icon {
top: 56% !important;
}
.slds-icon_small, .slds-icon--small {
width: 1.5rem;
height: 1.5rem;
line-height: 2;
}
To use this component in your lightning component first declare this component:
lwcLookupDemo.app
<aura:application extends="force:slds">
<aura:attribute name="selectRecordName" type="String" description="text" ></aura:attribute>
<aura:attribute name="selectRecordId" type="String" description="text" ></aura:attribute>
<lightning:card title="">
<c:lwcCustomLookup objectName="Account" fieldName="Name" selectRecordId="{!v.selectRecordId}"
selectRecordName="{!v.selectRecordName}" iconName = "action:new_account" onselected="{!c.selectedRecords}"/>
Selected Record Name: {!v.selectRecordName} <br/>
Selected Record Id: {!v.selectRecordId}
</lightning:card>
</aura:application>
lwcLookupDemoController.js
({
selectedRecords : function(component, event, helper) {
var selectRecName = event.getParam('selectName');
var selectRecId = event.getParam('currentRecId');
if(selectRecName != undefined) {
component.set("v.selectRecordName", selectRecName);
component.set("v.selectRecordId", selectRecId);
}
}
})
To pass data to parent component, we have used Events. You can read about them in detail here.
Now we will look into code. When user type input we call the controller method, we pass the string and in controller search for related records. We have used Imperative calling. You can read about it here. Then we are using template to iterate the result.
You can find complete code of Custom Lookup in Lightning Web Components in github-repo here.
Did you like the post or have any question, let me know in comments. Happy Programming 🙂
Cannot find the class -> lwcCustomLookupController. Could you please provide code for the class?
In the end I have added link to my github repo. You can refer that
Could you please provide apex controller to this lookup? I didn’t find it your git repo.
I have added that in Github. Please check.
Plese check now
Hi I didn’t find it in your repo 😦
Its wrong
https://github.com/tushar30/LWC-Lookup/blob/master/lwcCustomLookup/LWCDataTableController.cls
What is wrong here? I didn’t get your point.
Please check now.
you referred in component is different class and having git repo is different.please check and correct it.
Class updated. Please check.
A nice enhancement would be reading icon info from the SObject itself instead of relying on parent component to pass through. Something along the line of
//controller.js
@wire(getObjectInfo, { objectApiName: ‘$objectType’ })
_objectInfo({ data, error }) {
if (error) { console.error(error); }
if (data) {
this._iconColor = ‘background: #’ + data.themeInfo.color;
this._iconSrc = data.themeInfo.iconUrl
}
}
//template
The above code could be updated to allow parent component to override the SObject default icon if need to.
Instead of just a single record can you show regarding multiple record.Means when we are searching record we are doing it one at time.I want to see the list of searched records below the lookup field
I am working on that component.
my concern is if we are selecting record from lookup field instead of showing it in combo-box it should have a add,delete and refresh button.if we are clicking the add button it should display below the combo-box in proper format
Tushar,any update
You have mentioned about using the component, however I’m unable to relate the
onselected=”{!c.selectedRecords}” part of it. This piece of code is introducing exception. Is there anything that i’m missing.
What exception you are getting. This code is used to pass selected record to parent component and it is calling an event.
We need to define this method in parent component. I have updated my code to show this.
Hi Tushar,
I have used your code to replicate the custom lookup functionality.
I am encountering an error after selecting the lookup value .Please find the below error details.
Uncaught Unable to find action ‘selectedRecords’ on the controller of harshabr:AccountLookUp
Please let me know why I am facing this issue.I have copied the code from the github.
We need to define this method in parent component. I have updated my code to show this.
Thanks Tushar for the code update.
I see your below code
selectedRecords : function(component, event, helper) {
var selectRecName = event.getParam(‘selRecords’);
if(selectRecName != undefined) {
component.set(“v.selectedRecords”, selectRecName);
}
}
Even this is not working.
What does selReords contains?
Thanks in advance.
Regards,
Harsha BR
I have updated code and added one lightning app. Hope it will help you. Let me know if you still facing any challenge.
Thanks Tushar.
“Selected Record Name ” value is coming.But “Selected Record Id” is not coming.
I made changes in component controller. Please refer that.
It is working now.
Thanks a lot Tushar
Is this lwc control will work for relation lookup in salesforce mobile?
It will work in mobile.
How can we setup the default value for lookup?
You can check `setSelectedRecord` method. Create another method if recordId is not blank then set those fields in your custom method.
How can i pass the initial value to lookup control for edit form field?
provide example for setting up initial value for custom lookup control
How can we removed/hide header (c-lwc-custom-lookup > lightining-card > article > header ) from the custom control
Pass a variable and based on its value you can add css class
Thanks for the detailed explanation Tushar.
Is there any way we can display list of sobjects when searched in the search box..Like if Acc is searched, Account should be displayed.
Please suggest
Thanks for the detailed explanation.
Is there any way to display Sobject names when searched in the search box. Like if we search Acc, Account should be displayed.
Can you please suggest any solution
Yes, we are passing object name as attribute just create another dropdown and based on selection pass the object name.
when i call return object list in the component js, I’m not getting any result. Can you please suggest any changes
That I believe you added extra code. Its hard to tell.
Thanks for the detailed explanation.
Is there any way to display Sobject names when searched in the search box. Like if we search Acc, Account should be displayed.
Can you please suggest any solution
Thanks for the detailed explanation.
Is there any way that we can display list of sobjects when searched in the search box. Like when Acc is searched, Account should be displayed.
Can you please suggest any solution here
Thanks for the help.
Can we embed this lwc into another lwc?
If yes, can you please provide the code.
Thanks,
Viru
There are many sample provided in my blog you can check them.
Hi Tushar, after I selected lookup field, icon and selected text overlapping. What am I missing?
Looks like CSS issue to me. You can tweak CSS to handle this.
for some reason I am getting event.currentTarget is undefined in the `setSelectedRecord` method
I just tested it again and it is working fine. Make sure you have used the same tags.