Standard Salesforce input fields often fall short when users need to select multiple related records at once. Creating a custom multi-select lookup component in Lightning Web Components (LWC) delivers a sleek, flexible solution that drastically improves user experience.
Prerequisites
To follow along with this tutorial smoothly, ensure you have:
- Fundamental understanding of LWC, JavaScript, and HTML basics.
- Salesforce DX CLI installed and configured locally.
- An active Salesforce Developer Org or Scratch Org.
Step 1: Set Up the LWC Component
First, generate a new component in your workspace using the Salesforce CLI command below:
sfdx force:lightning:component:create -n MultiSelectLookup -d force-app/main/default/lwc
Open multiSelectLookup.js and add the foundational component structure with dynamic apex imports and toast handlers:
import { LightningElement, api, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import searchRecords from '@salesforce/apex/CustomController.searchRecords';
export default class MultiSelectLookup extends LightningElement {
@api selectedRecords = [];
@track searchResults = [];
handleSearch(event) {
const searchTerm = event.target.value;
if (!searchTerm) {
this.searchResults = [];
return;
}
searchRecords({ searchTerm: searchTerm })
.then((result) => {
this.searchResults = result;
})
.catch((error) => {
this.showToast('Error', error.body ? error.body.message : error.message, 'error');
});
}
handleRecordSelection(event) {
const selectedRecordId = event.currentTarget.dataset.recordId;
const selectedRecord = this.searchResults.find(record => record.Id === selectedRecordId);
if (selectedRecord && !this.selectedRecords.some(item => item.Id === selectedRecordId)) {
this.selectedRecords = [...this.selectedRecords, selectedRecord];
}
}
showToast(title, message, variant) {
const toastEvent = new ShowToastEvent({
title: title,
message: message,
variant: variant
});
this.dispatchEvent(toastEvent);
}
}
Step 2: Implement the Apex Controller
Create an Apex class named CustomController that performs SOQL queries based on the user's search text.
public with sharing class CustomController {
@AuraEnabled(cacheable=true)
public static List<SObject> searchRecords(String searchTerm) {
if (String.isBlank(searchTerm)) {
return new List<SObject>();
}
String key = '%' + searchTerm + '%';
return [SELECT Id, Name FROM Account WHERE Name LIKE :key LIMIT 10];
}
}
@AuraEnabled(cacheable=true) when fetching query results for LWC. Omitting this prevents wire adapters or wire-like client performance optimization.
Step 3: Build the Search and Selection UI
Open multiSelectLookup.html and render the search input and the interactive list overlay:
<template>
<lightning-card title="Multi-Select Lookup" icon-name="standard:search">
<div class="slds-p-around_medium">
<lightning-input
type="search"
label="Search Accounts"
onchange={handleSearch}
placeholder="Type to search...">
</lightning-input>
<template if:true={searchResults.length}>
<div class="slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid" style="position:relative;">
<ul class="slds-listbox slds-listbox_vertical" role="presentation">
<template for:each={searchResults} for:item="record">
<li key={record.Id} class="slds-listbox__item" onclick={handleRecordSelection} data-record-id={record.Id}>
<div class="slds-media slds-listbox__option slds-listbox__option_plain slds-media_center" role="option">
<span class="slds-media__body">
<span class="slds-truncate" title={record.Name}>{record.Name}</span>
</span>
</div>
</li>
</template>
</ul>
</div>
</template>
</div>
</template>
</template>
Step 4: Handle Selection and Display Options
Ensure your component cleanly updates state when items are added or removed from the selected list.
- Improved UX: Replaces bulky multi-select picklists with modern search inputs.
- Reusable Architecture: Can easily be adapted for Accounts, Contacts, or Custom Objects.
- Lightweight: Uses native Lightning Design System (SLDS) styling without external libraries.
Summary
By pairing Apex search logic with LWC reactivity, you can build seamless multi-select lookup inputs tailored to your specific org requirements. Customize the SOQL query and template pills to adapt this pattern for any standard or custom object.