Key de-bouncing on input in Lightning web component

Hello Trailblazers! If you are creating/have ever created a search input to search the records from the database this is the post for you. To implement this we usually call the apex method imperatively on change of the input from a Lightning web component.

This solution works just fine, but there is one problem, you must have observed that every time you type a key it immediately calls an imperative apex method without waiting for use to finish typing. So this is the problem where the search results are not consistent and the user experience is glitchy.

Apart from user experience, this will also help to reduce unwanted Apex server calls from the component.

To avoid this, we use a technique called key debouncing. In this post, I will tell you how to do key debouncing in the Lightning web component.

key-de-bouncing-on-input-lwc



How key de-bouncing works?

To implement key de-bouncing we will use a class JS delay technique to add 300ms(you can change this as per your requirement, but this is widely used.) delay on apex imperative callout using the setTimeout method from JavaScript. So basically, the component will wait for 300ms until the user inputs the next character, if the user enters the next character within 300ms then it will again start the timer to wait for another 300ms until the user stops typing.

This will save us a good amount of server calls and also component will not interfere until the user stops typing.


Example Scenario

I will create a simple component to search the contact records based on the entered search key. For this, we will create one Lightning web component and one apex class to run a SOSL on the Contact object records.

We will display the SOSL result in the Lightning Datatable.


Code and Implementation


Html code


<lightning-input
    class="slds-var-p-around_x-small"
    type="search"
    label="Search (With Key Debouncing)"
    placeholder="Type a word"
    onchange={handleSeachKeyChangeDebounced}>
</lightning-input>

Javascript Code


import { LightningElement } from "lwc";
import searchContacts from "@salesforce/apex/SearchController.searchContacts";
export default class App extends LightningElement {
    searchKeyDebounced;

    doneTypingInterval = 300;
    typingTimer;

    contacts;

    handleSeachKeyChangeDebounced(event){
        clearTimeout(this.typingTimer);

        let value = event.target.value;

        this.typingTimer = setTimeout(() => {
            if(value){
                searchContacts({ searchKey: value }).then((result) => {
                    this.contacts = result;
                })
            }
        }, this.doneTypingInterval);
    }
}

Apex Code


public class SearchController {

    @AuraEnabled
    public static List<Contact> searchContacts(String searchKey) {
        List<List<Sobject>> contactSearchResults = [
            FIND :searchKey
            IN ALL FIELDS
            RETURNING Contact(Name, Email)
            LIMIT 100
        ];
        if (!contactSearchResults.isEmpty()) {
            return (Contact[]) contactSearchResults[0];
        }
        return new List<Contact>();
    }
}


Live Playground Example

I have also created a simple playground to explain the difference between debounced input and regular input so you can check the difference between the two. You can find that example here.


2 comments:
  1. Hello,

    I noticed that we Cant directly Use event.target.value inside setTimeOut() method,
    And When i implemented it in setTimeOut(), My functionality or code was not working as expected,

    ReplyDelete
    Replies
    1. Hello, Yes you are right, thanks for reporting bug. It doesn't work because of closure. You need to define a var to store and pass that. I will update the post.

      Delete

Hi there, comments on this site are moderated, you might need to wait until your comment is published. Spam and promotions will be deleted. Sorry for the inconvenience but we have moderated the comments for the safety of this website users. If you have any concern, or if you are not able to comment for some reason, email us at rahul@forcetrails.com