custom reusable lookup in lwc using sosl
Hey there,
Welcome back 🙂 . Here in this blog post, we are going to develop a custom reusable lookup using SOSL.
Step 1 – Create ‘lwcsearchcomponent‘ component and use below code
lwcsearchcomponent.html
<template>
<lightning-input
type="search"
value={searckKeyword}
onchange={handleChange}
label={searchLabel}
> </lightning-input>
</template>
lwcsearchcomponent.js
import { LightningElement, api, track } from 'lwc';
export default class Lwcsearchcomponent extends LightningElement {
@track searckKeyword;
@api isrequired = 'false';
@api searchLabel = 'Search Account';
@api showLabel = 'true';
/* Check the isrequired prop is true then set the prop to true*/
renderedCallback() {
if ( this.isrequired === "false" )
return;
if ( this.isrequired === "true") {
let picklistInfo = this.template.querySelector('lightning-input');
picklistInfo.required = true;
this.isrequired = "false";
}
}
handleChange(event) {
var keyword = event.target.value;
/* Create & dispatch the event to parent component with the search keyword */
if ( keyword && keyword.length >= 2 ) {
let searchEvent = new CustomEvent('search',{
detail : { value : keyword }
});
this.dispatchEvent(searchEvent);
}
}
}
Step 2 – Create ‘lwcrecordlist‘ component and use below code.
lwcrecordlist.html
<template>
<li role="presentation" class="slds-listbox__item slds-p-top_small" onclick={handleSelect}>
<span id="listbox-option-unique-id-01"
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" title="Icon">
<lightning-icon icon-name={iconname} size="small"></lightning-icon>
<span class="slds-assistive-text">Icon</span>
</span>
</span>
<span class="slds-media__body">
<span class="slds-listbox__option-text slds-listbox__option-text_entity">{rec.Name}</span>
</span>
</span>
</li>
</template>
lwcrecordlist.js
import { LightningElement, api } from 'lwc';
export default class Lwcrecordlist extends LightningElement {
/* Public Property to pass the single record & iconname */
@api rec;
@api iconname = 'standard:account';
handleSelect( ) {
let selectEvent = new CustomEvent('select',{
detail : { selRec : this.rec }
});
this.dispatchEvent( selectEvent );
}
handleRemove( ) {
let selectEvent = new CustomEvent('select',{
detail : { selRec : undefined }
});
this.dispatchEvent( selectEvent );
}
}
Step 3 – create ‘CustomSearchController‘ apex class & use below code
CustomSearchController.apxc
public with sharing class CustomSearchController {
/* Create an Aura Enabled Method which tooks objectName, fieldtoSearch and the text to search */
/* Develop the Dynamic SOSL and then use Query method of Search Class to return the result */
@AuraEnabled
public static String searchRecords(String objName, String fieldName,
String searchKey){
String searchKeyword = searchKey + '*';
String returningQuery = objName+' ( Id, '+fieldName+')';
String query = 'FIND :searchKeyword IN ALL FIELDS RETURNING '+returningQuery+' LIMIT 2000';
List<List<sObject>> sobjectList = Search.query(Query);
return JSON.serialize(sobjectList);
}
}
Step 4 – Create ‘customlwclookup‘ component & use below code
customlwclookup.html
<template>
<div class="slds-m-padding_around">
<template if:false={selectedRecord} >
<c-lwcsearchcomponent onsearch={hanldeSearch} search-label={label}
isrequired="true" ></c-lwcsearchcomponent>
</template>
</div>
<div class="slds-m-padding_around">
<template if:false={selectedRecord} >
<template if:true={records}>
<template for:each={records} for:item="rec" for:index="index">
<ul key={rec.Id}
class="slds-listbox " >
<c-lwcrecordlist key={rec.Id} rec={rec}
iconname={iconname}
onselect={handleSelect}>
</c-lwcrecordlist>
</ul>
</template>
</template>
</template>
<template if:true={selectedRecord} >
<label class="slds-form-element__label" for="unique-id-of-input">
{label}
</label>
<div class="slds-pill-container">
<lightning-pill class="pillSize"
href="JavaScript:void(0);"
label={selectedRecord.Name}
name={selectedRecord.Name}
onremove={handleRemove}>
<lightning-icon icon-name={iconname} variant="circle"
alternative-text={objectName}></lightning-icon>
</lightning-pill>
</div>
</template>
</div>
</template>
customlwclookup.js
This component is required 4 public property to work the lookup for any object.
- objectName
- fieldName
- iconname
- label
- parentidfield
See the comments for more information
import { LightningElement, api, track } from 'lwc';
import searchRecords from '@salesforce/apex/CustomSearchController.searchRecords';
export default class Customlwclookup extends LightningElement {
/* public property */
/* these public property will be used when using this component inside other component for the lookup functionality */
/* objectName is the name of the Object which is parent either master-detail or lookup */
/* fieldName is the field of parent object in which text needs to be searched */
/* iconname - icon to display in the list and after selection of the record */
/* label - to show the label for the lookup */
/* parentidfield - the apiname of lookup/matser-detail in the child object this field is useful to indentify which parent record has been select if there are multiple lookup for a single child record */
@api objectName = 'Account';
@api fieldName = 'Name';
@api iconname = 'standard:record';
@api label = 'Account';
@api parentidfield = 'AccountId';
/* private property */
@track records;
@track selectedRecord;
hanldeSearch(event) {
var searchVal = event.detail.value;
searchRecords({
objName : this.objectName,
fieldName : this.fieldName,
searchKey : searchVal
})
.then( data => {
if ( data ) {
let parsedResponse = JSON.parse(data);
let searchRecordList = parsedResponse[0];
for ( let i=0; i < searchRecordList.length; i++ ) {
let record = searchRecordList[i];
record.Name = record[this.fieldName];
}
//window.console.log(' data ', searchRecordList);
this.records = searchRecordList;
}
})
.catch( error => {
window.console.log(' error ', error);
});
}
handleSelect(event) {
var selectedVal = event.detail.selRec;
this.selectedRecord = selectedVal;
let finalRecEvent = new CustomEvent('select',{
detail : { selectedRecordId : this.selectedRecord.Id, parentfield : this.parentidfield }
});
this.dispatchEvent(finalRecEvent);
}
handleRemove() {
this.selectedRecord = undefined;
this.records = undefined;
let finalRecEvent = new CustomEvent('select',{
detail : { selectedRecordId : undefined, parentfield : this.parentidfield }
});
this.dispatchEvent(finalRecEvent);
}
}
customlwclookup.css
.pillSize{
width: 100%;
}
Step 5 – Test the component
Create another component and use the below code for the same. In the below example, I have used the customlwclookup component 3 times. to test the functionality for Account, Case & Contact Object.
<template>
<lightning-card title="Lookup Demo" icon-name="standard:record">
<div class="slds-p-around_small">
<c-customlwclookup object-name="Account" field-name="Name"
label="Account" parentidfield="AccountId"
iconname="standard:account" ></c-customlwclookup>
</div>
<div class="slds-p-around_small">
<c-customlwclookup object-name="Case" field-name="Subject"
label="Case" parentidfield="Case__c"
iconname="standard:case" ></c-customlwclookup>
</div>
<div class="slds-p-around_small">
<c-customlwclookup object-name="Contact" field-name="Name"
label="Contact" parentidfield="ContactId"
iconname="standard:contact" ></c-customlwclookup>
</div>
</lightning-card>
</template>
Use below code for .xml file & after deploying the code into org. You can add this component inside home/record/app page and test the functionality
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>47.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Happy Learning 🙂 Keep Sharing 😉
#Salesforce #Trainhead #AskPanther #BeASalesforceChamp
https://testwebgrantha.xyz/sfdc/custom-reusable-lookup-in-lwc-using-sosl/
this is really bad that you have not provided layout.How this component would show.
Share screenshot
Can not you run the component and see the outcome? I mean this is really simple.
You can Use this link.