This blog will explain how to create Multi Select Look Up Component in LWC. This LWC component will work for below use cases.

1. When you have to build use case where user can select multiple values by searching in input field.(Multi look up).

2. When you have to build a use case where you have to select single value by searching (Single Select Look Up)

3. When you have to use a look up functionality by using extra filter criteria.

MultiSelectLookup.html

<template>

<lightning-card>

<div>

<div class="slds-form-element">

<div class="slds-form-element__control">

<div class="slds-combobox_container">

<div class={dynamiClassname} 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} data-id="userinput" label={Label} name="searchText" onchange={searchField} class="leftspace" disabled={disableInputField}></lightning-input>

<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 class="slds-form-element__control slds-input-has-icon slds-input-has-icon slds-input-has-icon_left-right" role="none">

<template for:each={selectedRecords} for:item="serecord">

<span key={serecord.recId}>

<lightning-pill label={serecord.recName} name={serecord.recId} onremove={removeRecord}>

<lightning-icon icon-name={iconName} variant="circle" alternative-text={serecord.recName}></lightning-icon>

</lightning-pill>

</span>

</template>

</div>

<!--Display Search 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>

MultiSelectLookUp.js

import { LightningElement,api,track } from 'lwc';

import getResults from '@salesforce/apex/MultiLookupController.getResults';

export default class LwcMultiLookup extends LightningElement {

@api objectName = 'User';

@api fieldName = '';

@api filterField = ''; //used to provide filter field in where clause

@api filterFieldValue= '';//used to provide filter field value in where clause

@api useFilterCriteria = false; // used to toggle the where clause in soql query

@api singleSelection = false; // used to toggle between single select and multi select

@track disableInputField = false;

@api Label;

@track searchRecords = [];

@track selectedIds = [];

@track selectedRecords=[];

@api selectedFromParent = [];

@api required = false;

@api iconName = 'action:new_user'

@api LoadingText = false;

@track dynamiClassname = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';

@track messageFlag = false;

connectedCallback() {

console.log('LookuoComponentinserted')

console.log(this.selectedFromParent);

if(this.selectedFromParent != undefined){

this.selectedRecords = [...this.selectedFromParent];

if(this.singleSelection){

this.disableInputField = true;

}

}

}

searchField(event) {

var currentText = event.target.value;

var selectRecId = [];

for(let i = 0; i < this.selectedRecords.length; i++){

selectRecId.push(this.selectedRecords[i].recId);

}

this.LoadingText = true;

getResults({ ObjectName: this.objectName, fieldName: this.fieldName, value: currentText, selectedRecId : selectRecId, useFilterCriteria: this.useFilterCriteria, filterField: this.filterField, filterFieldValue:this.filterFieldValue})

.then(result => {

this.searchRecords= result;

this.LoadingText = false;

//

this.dynamiClassname = 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 recId = event.currentTarget.dataset.id;

var selectName = event.currentTarget.dataset.name;

console.log(recId);

//console.log(selectName);

let newsObject = { 'recId' : recId ,'recName' : selectName };

this.selectedIds.push(recId);

this.selectedRecords.push(newsObject);

console.log(this.selectedIds);

this.txtclassname = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';

//let selRecords = this.selectedRecords;

this.template.querySelectorAll('lightning-input').forEach(each => {

each.value = '';

});

console.log('event dispatch');

//console.log(this.selectedIds);

let ids = this.selectedIds.toString();

console.log(ids);

const selectedEvent = new CustomEvent("userselected", {

detail: this.selectedRecords

});

// Dispatches the event.

this.dispatchEvent(selectedEvent);

if(this.singleSelection){

this.disableInputField = true;

}

}

removeRecord (event){

let selectRecId = [];

let selectedIds1 = [];

for(let i = 0; i < this.selectedRecords.length; i++){

if(event.detail.name !== this.selectedRecords[i].recId){

selectRecId.push(this.selectedRecords[i]);

selectedIds1.push(this.selectedRecords[i].recId)

}

}

this.selectedRecords = [...selectRecId];

this.selectedIds = [...selectedIds1];

let selRecords = this.selectedRecords;

let ids = this.selectedIds.toString();

if(this.singleSelection && selectRecId.length <=0){

this.disableInputField = false;

}

const selectedEvent = new CustomEvent('userselected', {

detail: this.selectedRecords

});

// Dispatches the event.

this.dispatchEvent(selectedEvent);

}

}

MultiSelectLookupController.cls

public without sharing class MultiLookupController {

public MultiLookupController() {

}

@AuraEnabled(cacheable=true)

public static List<SObJectResult> getResults(String ObjectName, String fieldName, String value, List<String> selectedRecId, Boolean useFilterCriteria, String filterField, String filterFieldValue) {

List<SObJectResult> sObjectResultList = new List<SObJectResult>();

system.debug(fieldName+'-------------'+ObjectName+'---++----------'+value+'====='+selectedRecId);

if(selectedRecId == null)

selectedRecId = new List<String>();

if(String.isNotEmpty(value)) {

String query = 'Select Id,';

if(useFilterCriteria){

query = query+ fieldName+' FROM '+ObjectName+' WHERE '+fieldName+' LIKE \'%' + value.trim() + '%\' and ID NOT IN: selectedRecId ';

query = query+' and '+filterField+'= \''+filterFieldValue+'\'';

}else{

query = query+ fieldName+' FROM '+ObjectName+' WHERE '+fieldName+' LIKE \'%' + value.trim() + '%\' and ID NOT IN: selectedRecId';

}

system.debug(query);

String fieldvalue = '';

for(sObject so : Database.Query(query)) {

fieldvalue = (String)so.get(fieldName);

sObjectResultList.add(new SObjectResult(fieldvalue, so.Id));

}

}

return sObjectResultList;

}

public class SObjectResult {

@AuraEnabled

public String recName;

@AuraEnabled

public Id recId;

public SObJectResult(String recNameTemp, Id recIdTemp) {

recName = recNameTemp;

recId = recIdTemp;

}

public SObJectResult() {

}

}

}

– By Manish Porwal, Senior Salesforce Developer – Venerate Solutions.

Covid-19 Update

A message to our customers.