LWC Components Used In this Project

  1. multiSelectPicklistLwc: In this component we can select multiple filters and we are showing catalog products according to filters
Filter Products
Filtered Products

multiSelectPicklistLwc JS Controller

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

export default class MultiSelectCombobox extends LightningElement {
    
    @api options;
    @api selectedValue;
    @api selectedValues = [];
    @api label;
    @api name;
    @api minChar = 2;
    @api disabled = false;
    @api multiSelect = false;
    @track value;
    @track values = [];
    @track optionData;
    @track searchString;
    @track message;
    @track showDropdown = false;

    connectedCallback() {
        this.showDropdown = false;
        var optionData = this.options ? (JSON.parse(JSON.stringify(this.options))) : null;
        var value = this.selectedValue ? (JSON.parse(JSON.stringify(this.selectedValue))) : null;
        var values = this.selectedValues ? (JSON.parse(JSON.stringify(this.selectedValues))) : null;
		if(value || values) {
            var searchString;
        	var count = 0;
            for(var i = 0; i < optionData.length; i++) {
                if(this.multiSelect) {
                    if(values.includes(optionData[i].value)) {
                        optionData[i].selected = true;
                        count++;
                    }  
                } else {
                    if(optionData[i].value == value) {
                        searchString = optionData[i].label;
                    }
                }
            }
            if(this.multiSelect)
                this.searchString = count + ' Option(s) Selected';
            else
                this.searchString = searchString;
        }
        this.value = value;
        this.values = values;
        this.optionData = optionData;
    }

    @api refresh(val) {
        
        this.selectedValue = val;
        this.showDropdown = false;
        var optionData = this.options ? (JSON.parse(JSON.stringify(this.options))) : null;
        var value = this.selectedValue ? (JSON.parse(JSON.stringify(this.selectedValue))) : null;
        var values = this.selectedValues ? (JSON.parse(JSON.stringify(this.selectedValues))) : null;
		if(value || values) {
            var searchString;
        	var count = 0;
            for(var i = 0; i < optionData.length; i++) {
                if(this.multiSelect) {
                    if(values.includes(optionData[i].value)) {
                        optionData[i].selected = true;
                        count++;
                    }  
                } else {
                    if(optionData[i].value == value) {
                        searchString = optionData[i].label;
                    }
                }
            }
            if(this.multiSelect)
                this.searchString = count + ' Option(s) Selected';
            else
                this.searchString = searchString;
        }
        this.value = value;
        this.values = values;
        this.optionData = optionData;
    }
    
    filterOptions(event) {
        this.searchString = event.target.value;
        if( this.searchString && this.searchString.length > 0 ) {
            this.message = '';
            if(this.searchString.length >= this.minChar) {
                var flag = true;
                for(var i = 0; i < this.optionData.length; i++) {
                    if(this.optionData[i].label.toLowerCase().trim().startsWith(this.searchString.toLowerCase().trim())) {
                        this.optionData[i].isVisible = true;
                        flag = false;
                    } else {
                        this.optionData[i].isVisible = false;
                    }
                }
                if(flag) {
                    this.message = "No results found for '" + this.searchString + "'";
                }
            }
            this.showDropdown = true;
        } else {
            this.showDropdown = false;
        }
	}

    selectItem(event) {
        var selectedVal = event.currentTarget.dataset.id;
        if(selectedVal) {
            var count = 0;
            var options = JSON.parse(JSON.stringify(this.optionData));
            for(var i = 0; i < options.length; i++) {
                if(options[i].value === selectedVal) {
                    if(this.multiSelect) {
                        if(this.values.includes(options[i].value)) {
                            this.values.splice(this.values.indexOf(options[i].value), 1);
                        } else {
                            this.values.push(options[i].value);
                        }
                        options[i].selected = options[i].selected ? false : true;   
                    } else {
                        this.value = options[i].value;
                        this.searchString = options[i].label;
                    }
                }
                if(options[i].selected) {
                    count++;
                }
            }
            this.optionData = options;
            if(this.multiSelect)
                this.searchString = count + ' Option(s) Selected';
            if(this.multiSelect)
                event.preventDefault();
            else
                this.showDropdown = false;
        }
    }

    showOptions() {
        if(this.disabled == false && this.options) {
            this.message = '';
            this.searchString = '';
            var options = JSON.parse(JSON.stringify(this.optionData));
            for(var i = 0; i < options.length; i++) {
                options[i].isVisible = true;
            }
            if(options.length > 0) {
                this.showDropdown = true;
            }
            this.optionData = options;
        }
	}

    removePill(event) {
        var value = event.currentTarget.name;
        var count = 0;
        var options = JSON.parse(JSON.stringify(this.optionData));
        for(var i = 0; i < options.length; i++) {
            if(options[i].value === value) {
                options[i].selected = false;
                this.values.splice(this.values.indexOf(options[i].value), 1);
            }
            if(options[i].selected) {
                count++;
            }
        }
        this.optionData = options;
        if(this.multiSelect)
            this.searchString = count + ' Option(s) Selected';

            this.dispatchValue();

    }

    blurEvent() {
        var previousLabel;
        var count = 0;
        for(var i = 0; i < this.optionData.length; i++) {
            if(this.optionData[i].value === this.value) {
                previousLabel = this.optionData[i].label;
            }
            if(this.optionData[i].selected) {
                count++;
            }
        }
        if(this.multiSelect)
        	this.searchString = count + ' Option(s) Selected';
        else
        	this.searchString = previousLabel;
        
        this.showDropdown = false;

        this.dispatchValue();
        
    }

    
    dispatchValue(){
        this.dispatchEvent(new CustomEvent('select', {
            detail: {
                'payloadType' : 'multi-select',
                'name': this.name,
                'payload' : {
                    'value' : this.value,
                    'values' : this.values
                }
            }
        }));
    }
}

multiSelectPicklistLwc HTML

<template>
    
    <!-- Header Label -->
    <template if:true={label}>
        <label class="slds-form-element__label">{label}</label>
    </template>
    <div class="slds-combobox_container">
        <div class="slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open" aria-expanded="true" aria-haspopup="listbox" role="combobox">
            <!-- Search Input -->
            <div class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right" role="none">
                <lightning-input disabled={disabled} class="inputBox" placeholder="Select an Option" onblur={blurEvent} onclick={showOptions} onkeyup={filterOptions} value={searchString} auto-complete="off" variant="label-hidden" id="combobox-id-1" ></lightning-input>
                <lightning-icon class="slds-input__icon" icon-name="utility:down" size="x-small" alternative-text="search"></lightning-icon>
            </div>
            <!-- Dropdown List -->
            <template if:true={showDropdown}>
                <div id="listbox-id-1" class="slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid"><!--style="{! 'max-height:' + (8 + (v.recordCount * 40)) + 'px' }""-->
                    <ul class="slds-listbox slds-listbox_vertical recordListBox" role="presentation">
                        <template if:false={message} >
                            <template for:each={optionData} for:item="option">
                                <template if:true={option.isVisible}>
                                    <li key={option.value} data-id={option.value} onmousedown={selectItem} class="slds-listbox__item eachItem">
                                        <template if:true={option.selected}>
                                            <lightning-icon icon-name="utility:check" size="x-small" alternative-text="icon" ></lightning-icon>
                                        </template>
                                        <span class="slds-media slds-listbox__option_entity verticalAlign slds-truncate">{option.label}</span>
                                    </li>
                                </template>
                            </template>
                        </template>
                        <template if:true={message} >
                            <li class="slds-listbox__item">
                                <span class="slds-media slds-listbox__option_entity verticalAlign slds-truncate">{message}</span>
                            </li>
                        </template>
                    </ul>
                </div>
            </template>
        </div>
    </div>
    <!-- Multi Select Pills -->
    <template for:each={optionData} for:item="option">
        <template if:true={option.selected}>
            <lightning-pill key={option.value} class="slds-m-around_xx-small" name={option.value} label={option.label} onremove={removePill}></lightning-pill>
        </template>
    </template>
</template>

multiSelectPicklistLwc CSS

.verticalAlign {
	cursor: pointer;
    padding: 0px 5px !important;
}
.slds-dropdown {
    padding:0px !important;
}
.recordListBox {
	margin-top:0px !important;
	overflow-y: scroll;
}
.slds-listbox li {
    padding: .45rem 0.7rem !important;
    display: flex;
}
.inputBox input {
	padding-left: 10px;
}
.eachItem:hover {
    background-color: #F1F1F1;
    cursor: pointer;
}

/* For Scrolling */
::-webkit-scrollbar {
    width: 7px;
    height: 7px;
}
::-webkit-scrollbar-track {
   display: none !important;
}
::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background: rgba(0,0,0,0.4);
}