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
- 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
