5

Hello guys I have a lightning combobox that has like 600 values. I would like to be able to search the values instead of scrolling.

My .js code is this one:

picklistOrdered = [];
    connectedCallback(){
        getValuesFromTable().then((result) => {
            this.picklistOrdered = result.map(({value: label, key: value}) => ({ label,value}))
            this.picklistOrdered = this.picklistOrdered.sort((a,b)=>{
                if(a.label < b.label){
                    return -1
                }
            })
        })
    }

Could someone help me and put an example? Thanks

10
  • you can press buttons on keyboard after clicking at the combobox, it will jump to the values based on the letter key you press. Commented Feb 10, 2023 at 8:36
  • @AntonKutishevsky yeah but that is not what I want I want to be able to put an input and search by that
    – TechGuy
    Commented Feb 10, 2023 at 8:39
  • got it, I have a suggestion. will put in an answer Commented Feb 10, 2023 at 8:40
  • 1
    The input has to be in the combobox
    – TechGuy
    Commented Feb 10, 2023 at 9:06
  • 2
    You will have to go with a custom component, I needed one some time ago, and I think this is the one I have used in the end github.com/benedwards44/lwc-combobox-autocomplete
    – Damecek
    Commented Feb 10, 2023 at 9:11

1 Answer 1

11

UPDATED: Implemented functionality to hide the dropdown when clicking outside of it.

This is a simplified implementation of the "searchable combobox" concept suggested by Damecek in the comments.

It utilizes the standard lightning-input component (set to type "search") and the SLDS combobox options blueprint to mimic the standard appearance. It includes the basic functionality of displaying all options when the input is focused (as the default combobox does) and filters picklist options based on the user's input.

HTML

<template>
    <div class="slds-card slds-p-around_medium">
        <div class="slds-form-element">
            <div class="slds-form-element__control">
                <lightning-input
                    label="Searchable Combobox"
                    onchange={search}
                    onfocus={showPickListOptions}
                    type="search"
                    value={selectedValue}
                >
                </lightning-input>

                <div 
                    if:true={searchResults}
                    class="slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid"
                    role="listbox"
                >
                    <ul class="slds-listbox slds-listbox_vertical" role="presentation">
                        <template for:each={searchResults} for:item="searchResult">
                            <li 
                                key={searchResult.value} 
                                data-value={searchResult.value} 
                                role="presentation" 
                                onclick={selectSearchResult} 
                                class="slds-listbox__item"
                            >
                                <div 
                                    class="slds-media slds-listbox__option slds-listbox__option_plain slds-media_small" 
                                    role="option"
                                >
                                    <span class="slds-media__body">
                                        <span 
                                            class="slds-truncate" 
                                            title={searchResult.label}
                                        >
                                            {searchResult.label}
                                        </span>
                                    </span>
                                </div>
                            </li>
                        </template>
                    </ul>
                </div> 
            </div>
        </div>
    </div>
</template>

JavaScript

import { LightningElement } from "lwc";
import getAccounts from "@salesforce/apex/SearchableComboboxController.getAccounts";

export default class SearchableCombobox extends LightningElement {
    isListening = false;

    pickListOrdered;
    searchResults;
    selectedSearchResult;

    get selectedValue() {
        return this.selectedSearchResult?.label ?? null;
    }

    connectedCallback() {
        getAccounts().then((result) => {
            this.pickListOrdered = result.sort((a, b) =>
                a.label.localeCompare(b.label)
            );
        });
    }

    renderedCallback() {
        if (this.isListening) return;

        window.addEventListener("click", (event) => {
            this.hideDropdown(event);
        });
        this.isListening = true;
    }

    /**
     * This function compares the name of the component (`cmpName`) with the name of the clicked element (`clickedElementSrcName`).
     * If the clicked element is outside the component, the dropdown (search results) is hidden by calling `clearSearchResults()`.
     *
     * - `cmpName` is the tag name of the host element of this component (e.g., 'C-SEARCHABLE-COMBOBOX').
     * - `clickedElementSrcName` is the tag name of the element that was clicked on the page.
     * - `isClickedOutside` is a boolean that is true if the clicked element is outside the component.
     */
    hideDropdown(event) {
        const cmpName = this.template.host.tagName;
        const clickedElementSrcName = event.target.tagName;
        const isClickedOutside = cmpName !== clickedElementSrcName;
        if (this.searchResults && isClickedOutside) {
            this.clearSearchResults();
        }
    }

    search(event) {
        const input = event.detail.value.toLowerCase();
        const result = this.pickListOrdered.filter((pickListOption) =>
            pickListOption.label.toLowerCase().includes(input)
        );
        this.searchResults = result;
    }

    selectSearchResult(event) {
        const selectedValue = event.currentTarget.dataset.value;
        this.selectedSearchResult = this.pickListOrdered.find(
            (pickListOption) => pickListOption.value === selectedValue
        );
        this.clearSearchResults();
    }

    clearSearchResults() {
        this.searchResults = null;
    }

    showPickListOptions() {
        if (!this.searchResults) {
            this.searchResults = this.pickListOrdered;
        }
    }
}

Demo and source code

Source Code

demo

12
  • can you share the options? and how did you put them in the html?
    – TechGuy
    Commented Feb 10, 2023 at 12:53
  • connectedCallback logic is the same as yours, I just have a list of accounts in my case. take a look at the showPicklistOptions method from my answer. it just shows a list of picklist options from connectedCallback if search is not being performed Commented Feb 10, 2023 at 12:56
  • 1
    for the on blur, I think I had div with backdrop slds class and on click event which hide the list
    – Damecek
    Commented Feb 10, 2023 at 14:49
  • 1
    for the on blur, just call clearSearchResults
    – Abbas
    Commented Jun 16, 2023 at 4:45
  • @Abbas the problem with it, onblur will be triggered when you click on the option you want to select Commented Jun 16, 2023 at 9:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .