Combobox with Searchbox Picklist Salesforce LWC: Searchable Picklist with Search Box, Sorting & ValidationCombobox with Searchbox Picklist

In many Salesforce Lightning projects, users expect picklists to be more interactive than the standard <lightning-combobox>.
If you’ve ever needed a searchable picklist with dropdown filtering, required field validation, and custom styling, this Lightning Web Component (LWC) is a ready-to-use solution.

Key Features

  • Search as you type — instantly filters picklist values
  • Required field validation with error messages
  • Works with static or dynamically loaded options
  • Dropdown closes automatically when clicking outside
  • Fully stylable via static resource CSS
  • Dispatches selection events back to parent components or Flows
  • Pickup drag optrion on search list

LWC Code

 
<template>
    <div class=”custom-picklist-container slds-form-element”>
        <div class=”slds-form-element__control slds-combobox_container”>
            <div class=”slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open” role=”combobox”>
                <div class=”slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right”>
                    <lightning-input type=”text” value={selectedValueShow} placeholder={placeholder}
                        onchange={handleSearchChange} onfocus={handleFocus} onblur={handleInputBlur} 
                        variant=”label-hidden” disabled={disabledornot}> 
                    </lightning-input>
                    <span class=”slds-icon_container slds-input__icon slds-input__icon_right iconPosition” style=”position: absolute; top: 14px;”>
                        <lightning-icon icon-name=”utility:down”
                                        size=”xx-small”
                                        alternative-text=”Dropdown”></lightning-icon>
                    </span>
                </div>

                <template if:true={showError}>
                    <div class=”slds-form-element__help slds-text-color_error”>
                        {errorMessage}
                    </div>
                </template>

                <template if:true={showDropdown}>
                    <div class=”slds-dropdown slds-dropdown_length-4 slds-dropdown_fluid” role=”listbox”
                        style=”max-height: 200px; overflow-y: auto;” onmousedown={handleDropdownMouseDown}>
                        <ul class=”slds-listbox slds-listbox_vertical” role=”presentation”>
                            <template for:each={filteredOptions} for:item=”option”>
                                <li key={option.value} class=”slds-listbox__item” role=”presentation”
                                    data-value={option.value} onmousedown={handleOptionMouseDown}>
                                    <div class=”slds-listbox__option slds-listbox__option_plain” role=”option”>
                                        {option.label}
                                    </div>
                                </li>
                            </template>
                        </ul>
                    </div>
                </template>
            </div>
        </div>
    </div>
</template>

LWC JavaScript

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

export default class SearchablePicklist extends LightningElement {
    @api placeholder = '';
    @api options = [];
    @api disabledornot = false;
    @api required = false;
    @api selectedvalue;
    @track searchKey = '';
    @track showDropdown = false;
    @track errorMessage = '';
    @track showError = false;

    isInteractingWithDropdown = false;

    get filteredOptions() {
        if (!this.options || !Array.isArray(this.options)) {
            return [];
        }
        if (!this.searchKey) {
            return this.options;
        }
        return this.options.filter(option =>
            option.label?.toLowerCase().includes(this.searchKey.toLowerCase())
        );
    }

    get selectedValueShow() {
        return this.selectedvalue ? this.selectedvalue : '';
    }


    handleSearchChange(event) {
        this.searchKey = event.target.value;
        this.showDropdown = true;
        this.errorMessage = '';
        this.showError = false;
    }

    handleFocus() {
        this.errorMessage = '';
        this.showError = false;
        if (!this.selectedvalue) {
            this.searchKey = '';
        }
        this.showDropdown = true;
    }

    handleInputBlur() {
        setTimeout(() => {
            if (!this.isInteractingWithDropdown) {
                this.showDropdown = false;
                const inputValue = this.template.querySelector('lightning-input').value.trim();
                this.searchKey = inputValue;
                const selectedOption = this.options.find(opt => opt.label === inputValue);

                if (selectedOption) {
                    this.selectedvalue = selectedOption.label;
                    this.searchKey = selectedOption.label;
                    this.errorMessage = '';
                    this.showError = false;
                    this.dispatchEvent(new CustomEvent('select', {
                        detail: { label: selectedOption.label, value: selectedOption.value }
                    }));
                } else if (!inputValue) {
                    this.errorMessage = 'This field is required.';
                    this.showError = true;
                    this.selectedvalue = '';
                    this.searchKey = '';
                    this.dispatchEvent(new CustomEvent('select', { detail: { label: '', value: '' } }));
                } else {
                    this.errorMessage = 'Please select a value from the dropdown.';
                    this.showError = true;
                    this.selectedvalue = '';
                    this.searchKey = '';
                    this.dispatchEvent(new CustomEvent('select', { detail: { label: '', value: '' } }));
                }
            }
            this.isInteractingWithDropdown = false;
        }, 300);
    }

    handleDropdownMouseDown() {
        this.isInteractingWithDropdown = true;
    }

    handleOptionMouseDown(event) {
        const selectedValue = event.currentTarget.dataset.value;
        const selectedOption = this.options.find(opt => opt.value === selectedValue);

        if (selectedOption) {
            this.searchKey = selectedOption.label;
            this.selectedvalue = selectedOption.label;
            this.showDropdown = false;
            this.errorMessage = '';
            this.showError = false;

            this.dispatchEvent(new CustomEvent('select', {
                detail: { label: selectedOption.label, value: selectedOption.value }
            }));
        }

        this.isInteractingWithDropdown = true;
        setTimeout(() => {
            this.isInteractingWithDropdown = false;
        }, 50);
    }
}

How to Use

  1. Deploy the component to your Salesforce org.
    2. Import and use it inside another LWC or Aura component:

<c-searchable-picklist
    placeholder="Select an option"
    options={myOptions}
    onselect={handleSelection}>
</c-searchable-picklist>

3. Pass options in the format:

myOptions = [
    { label: 'Option A', value: 'A' },
    { label: 'Option B', value: 'B' }
];

Conclusion

This LWC provides a modern, user-friendly picklist that enhances data entry efficiency while maintaining validation rules.
It’s reusable in multiple places — from record pages to Flow screens — and completely customizable.

You can use this as Searchbox when you change combobox to inputbox.

Thanks for visiting — by Sunil

Scroll to Top