Lightning Web Components: Multi Select Custom Lookup

Lightning Web Components (LWC) is current Trending technology in Salesforce Lightning Eco System. I have shared many post related to LWC which you can check to quickly get the idea. Today I will share Multi Select Custom Lookup in LWC.

Multi Select Custom lookup in lightning Web Component LWC

Previously I have shared Custom Lookup in Lightning web Component but in that we can only select one record, Sometimes there is requirement where we need to aloow users to select multiple records. We don’t have any standard component available for this functionality so I have created below component. As this is generic component so you can use it with any object.

Now we will check the code part.


        <h3 slot="title">
            <lightning-icon icon-name="utility:connected_apps" size="small"></lightning-icon>
            Multi Select Custom Lookup in Lightning Web Components
        <div slot="footer">
            <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">
                                    <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>
                                <lightning-input required={required} data-id="userinput" label={Label} name="searchText" onchange={searchField} class="leftspace"></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>
                            <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>
                            <!-- 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 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>
                            <div if:true={messageFlag}>
                                No result found.
                            <div if:true={LoadingText}>

Here we are displaying selected records on UI and also allowing users to select next record. User can easily cick on cancel icon to remove select records.


import { LightningElement,api,track } from 'lwc';
import getResults from '@salesforce/apex/lwcMultiLookupController.getResults';

export default class LwcMultiLookup extends LightningElement {
    @api objectName = 'Account';
    @api fieldName = 'Name';
    @api Label;
    @track searchRecords = [];
    @track selectedRecords = [];
    @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;
    searchField(event) {

        var currentText =;
        var selectRecId = [];
        for(let i = 0; i < this.selectedRecords.length; i++){
        this.LoadingText = true;
        getResults({ ObjectName: this.objectName, fieldName: this.fieldName, value: currentText, selectedRecId : selectRecId })
        .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 => {
   setSelectedRecord(event) {
        var recId =;
        var selectName =;
        let newsObject = { 'recId' : recId ,'recName' : selectName };
        this.txtclassname =  'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';
        let selRecords = this.selectedRecords;
		this.template.querySelectorAll('lightning-input').forEach(each => {
            each.value = '';
        const selectedEvent = new CustomEvent('selected', { detail: {selRecords}, });
        // Dispatches the event.

    removeRecord (event){
        let selectRecId = [];
        for(let i = 0; i < this.selectedRecords.length; i++){
            if( !== this.selectedRecords[i].recId)
        this.selectedRecords = [...selectRecId];
        let selRecords = this.selectedRecords;
        const selectedEvent = new CustomEvent('selected', { detail: {selRecords}, });
        // Dispatches the event.

In Controller SearchField we are passing the current user txet in controller with the already selected record ids. We are passing existing record ids so that we can filter those records. Once user select any record from dropdown we fire the setSelectedRecord method and add the selected record in selectedRecords array. We are also sending an event to pass selected records to parent components. Once user click on remove icon we simply remove that reord from the array.


public with sharing class lwcMultiLookupController {
    public lwcMultiLookupController() {

    public static List<SObJectResult> getResults(String ObjectName, String fieldName, String value, List<String> selectedRecId) {
        List<SObJectResult> sObjectResultList = new List<SObJectResult>();
        if(selectedRecId == null)
            selectedRecId = new List<String>();

        if(String.isNotEmpty(value)) {
            String query = 'Select Id,'+fieldName+' FROM '+ObjectName+' WHERE '+fieldName+' LIKE \'%' + value.trim() + '%\' and ID NOT IN: selectedRecId';
            for(sObject so : Database.Query(query)) {
                String fieldvalue = (String)so.get(fieldName);
                sObjectResultList.add(new SObjectResult(fieldvalue, so.Id));
        return sObjectResultList;
    public class SObjectResult {
        public String recName;
        public Id recId;
        public SObJectResult(String recNameTemp, Id recIdTemp) {
            recName = recNameTemp;
            recId = recIdTemp;
        public SObJectResult() {

This is a simple apex controller we are making dynamic SOQL to get records based on user input and sending back to lwccontroller. We are using wrapper to pass data. Wrapper allow us to easily handle the data with any object.
We have created one custom app in lightning, using this app we are passing data from LWC to Lightning component. We have only created this app for demo purpose. You can get the selected records and can use in your existing components.

<aura:attribute name="selectedRecords" type="lwcMultiLookupController.SObjectResult[]" description="text" ></aura:attribute>
<lightning:card title="">
    <c:lwcMultiLookup objectName="Account" fieldName="Name" 
                      iconName = "standard:account" onselected="{!c.selectedRecords}"/>

    <div class="slds-page-header">
        <div class="slds-media">
            <div class="slds-media__figure">
                <span class="slds-icon_container slds-icon-standard-opportunity" title="Account Record">
            <div class="slds-media__body">
                <h1 class="slds-page-header__title slds-truncate slds-align-middle" title="Account Record">Accounts</h1>
                <p class="slds-text-body_small slds-line-height_reset"></p>
    <table class="slds-table slds-table_bordered slds-table_cell-buffer">
            <tr class="slds-text-title_caps">
                <th scope="col">
                    <div class="slds-truncate" title="Account Id">Account Id</div>
                <th scope="col">
                    <div class="slds-truncate" title="Account Name">Account Name</div>
            <aura:iteration var="selectRec" items="{!v.selectedRecords}">
                    <th scope="row" data-label="Account Id">
                        <div class="slds-truncate" title="{!selectRec.recId}"><a id="{!selectRec.recId}">{!selectRec.recId}</a></div>
                    <td data-label="Account Name">
                        <div class="slds-truncate" title="{!selectRec.recName}">{!selectRec.recName}</div>


    selectedRecords : function(component, event, helper) {
        var selectRecName = event.getParam('selRecords');
        if(selectRecName != undefined) {
            component.set("v.selectedRecords", selectRecName);

Here I have share complete code for Multi Select Custom Lookup LWC. Code is pretty simple and I have just modify the Lookup code. Now we are filtering the selected records in SOQL and passing a list of array in parent Lightning Component.

In this post we have also covered how to use wrapper in Lightning or Lightning Web Components.

Did you liked this post or have any suggestions, let me know in comments. Happy programming 🙂


10 thoughts on “Lightning Web Components: Multi Select Custom Lookup

  1. Thanks Tushar, I have recently found out your blog and I am very pleased to say that it is one of the best sf blog. I really appreciate your knowledge sharing. Keep rocking bro !!

  2. Hi, wanted to understand where is the code to save the Account on the parent object. we are selecting multiple records but where are we saving these. also if i wanted this on the related list functionality, where users can select mutiple records and selected records should be the child records to the parent. For Example on Campaign object I want two related list and both for contact, lets say contact1 and contact2 and these shuld not allow user to create new records they must be able to multiselect contact and save them as related records to campaign.

  3. I love this. How much more of an effort would it take to select a range ( click 1 item then shift+click several items below to select the range)?

  4. Thanks a lot, Tushar for this! It was extremely helpful!
    Also, I have a requirement here that I restrict the number of values selected to 2. What will be the best way to handle that, can you please suggest?

  5. @ Tushar, Thanks a lot for sharing this functionality with us.

    Use Case – I have Project__c Object Contact Object
    Now business wants functionality to add multiple Contacts to Project from UI quickly.
    My Approach – Created Lightning Action button on Project__c which calls my Screen Flow then added it to Project Page Layout. Now when Flow starts it has Project RecordId to start with, On first flow screen I have added your LWC lwcMultiLookup Component via Master Component (copied Demo App Code you provided in Master Component).
    So now user can use the search bar to find contacts and quickly select the ones they would like to associate with Project. All works great until the selection part but I am having trouble with storing the selectedRecords List/String as a variable in my Flow to further run Loop on and create Project_Relationship Records.

    Steps Followd –

    1. Created the LWC as per your instructions above and also created a master component “lwcMultiLookupRecords” (copied Demo App Code you provided in Master Component) which calls the LWC.
    2. Replaced all references from Account to Contact in both Master Component and LWC.
    3. Updated lwc/lwcMultiLookup/lwcMultiLookup.js-meta.xml file
    3.i. true
    3.ii. lightning__FlowScreen

    4. on Master Component added implements=”lightning:availableForFlowScreens”
    5. For Master Component added design “”

    4. Added the LWC in Flow -> Screen Element.

    Saved the Flow and when I run it lets me select all the contacts i want and adds it under the search bar .. but the Contacts table underneath as shown in your demo app doesnt display the records & I cant seem to store the selectedRecords into variable.

    Is it because of selectedRecords Type being SObjectResult[] ?
    What changes would you suggest I make so that once i select all the contacts the selectedRecords provides me a Array of Ids or Contact records or String collection variable that i can iterate over using Loop and insert Project_Relationship junction association records (one for each contact against the project where user started the flow)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.