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.
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.
Hello,
ReplyDeleteI 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,
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