Test LWC with Jest

Jest is a powerful JavaScript testing framework for the client-side project. It’s supported in any React Application, Node, Babel, TypeScript as well as Salesforce Lightning Web Component.Jest uses jsdom to provide an environment like a browser’s Document Object Model(DOM).

Jest can be used for

  • Test a component in isolation
  • Test a component’s public API (@api properties and methods, events)
  • Test basic user interaction (clicks)
  • Verify the DOM output of a component
  • Verify that events fire when expected

In this session, we will see how to test a simple Lightning Web Component using Jest framework.

To test Lightning Web Component, need to install sfdx-lwc-jest and its dependencies into Salesforce DX Project. jsdom is downloaded during the installation of lwc-jest.

First, we need to set up the environment to work with Jest in Salesforce DX project.

  • Install Node.js from this link:  https://nodejs.org/en/, if you have not installed in your computer yet. Set the Environment Path to access npm from any drive location.
  • Generally, Salesforce DX Project doesn’t have a package.json file. Run the following command as “npm init” from the terminal of the Visual Studio Code and it will create a package.json file in the project directory. After “npm init” execution, system will ask you the project information, for now you can keep it as blank. You just need to enter until package.json file has been created.
  • To install lwc-jest and its dependencies, please run the following commands one by one:
npm install
npm install @salesforce/sfdx-lwc-jest --save-dev

It will take some time to complete the downloading of sfdx-lwc-jest and its dependencies in your SFDX project library.

  • Need to update the <scripts> block of the package.json file by adding the following codes.
"test:unit": "lwc-jest",
"test:unit:watch": "lwc-jest --watch",
"test:unit:debug": "lwc-jest --debug",
"test:unit:coverage": "lwc-jest --coverage"

N.B.- Please check the latest release on sfdx-lwc-jest, may be you need to update “lwc-jest” to “sfdx-lwc-jest” for “test:unit” snippet if the upper code snippets will not work.

  • Create a folder named “__tests__” in the specific Lightning Web Component folder in the SFDX project.
  • Update the .forceignore file to ensure that the files of the “__tests__” folder should not be deployed during deployment of the lightning web component into the Salesforce Org. Please update the “.forceignore” file  according to the following line:

           **/__tests__/**

Setup is done. Awesome!! You have done a great job. Take rest..we will move to the next section how to run Jest to test Lightning Web Component.

Naming Convention of Test File: LightningWebComponentName.test.js

Now, we will create the test file into the “__tests__” folder.

Let’s say following is the Lightning Web Component named “welcomeWindow”

welcomeWindow.html

<template>
    <lightning-card title="Welcome My Friends">
        <div class="messageClass">    
            <lightning-layout><!--if horizontal-align="space", all layout items will be in center-->
                    <lightning-layout-item flexibility="auto" padding="around-small"> 
                        <div class="contentClass">                   
                            Welcome to LWC Training Class
                        </div>
                    </lightning-layout-item>
            </lightning-layout>
        </div>
    </lightning-card>     
</template>

After that, we will create a welcomeWindow.test.js file into the “__tests__” folder. Now we will write the code into this file like:

welcomeWindow.test.js

import { createElement } from 'lwc';
import WELCOMEWINDOW from 'c/welcomeWindow';

describe('c-welcome-window', () => {
    afterEach(() => {
        while (document.body.firstChild) {
            document.body.removeChild(document.body.firstChild);
        }
    });

    it('displays greeting', () => {
        // Create element
        const element = createElement('c-welcome-window', {
            is: WELCOMEWINDOW
        });
        document.body.appendChild(element);
        // Verify displayed welcome message
        const div = element.shadowRoot.querySelector('div');
        expect(div.textContent).toBe('Welcome to LWC Training Class');
    });
});

Clarification of the welcomeWindow.test.js file

  • Imports standard methods: First, we need to import the standard “createElement” method and import the Lightning Web Component to test. Here, we will test “welcomeWindow” Lightning Web Component.
  • Describe() block: Next, we will focus on the describe block. This block is nothing but a test suite. A single describe block can be used to test more business cases. afterReach() method resets the DOM at the end of the test.
  • it block: We can say it block as test block. A single it block describes a single test.
  • Component Creation: In the it block, we need to create an instance of the original LWC to test by “createElement()” method.
  • Adding the Component into DOM: After that, we need to add the component instance into the DOM by appendChild method.
  • Asserts: Now, we need to elements from the DOM using querySelector() method. Finally, we need to put the expect statement which is an assertion of the success condition. Here, we have written just like:

expect(div.textContent).toBe(‘Welcome to LWC Training Class’); //where the value of div.textContent will match the                     string in toBe() method.

Jest supports lots of matchers like toBe and toMatchObject. Please check all the methods from this link:
https://jestjs.io/docs/en/expect

How to run the test?

Now, we need to run the following code in the terminal of VS Code to test our lightning component.

npm run test:unit

When this command will be executed, it will run the respective code snippet “lwc-jest” mentioned in the script block of the package.json file.

So, after running this command, we will get the following output in the terminal of our VS Code.

 

 

 

 

 

 

 

if we will update the welcomeWindow.test.js file with line no. 19 as

expect(div.textContent).toBe('Welcome to Lightning Web Component Training Class');

and run the unit test again, we will see the error message as mentioned in the following image


 

 

 

 

 

 

 

 

 

 

 

Thank you!! So, we have explored how to test a simple Lightning Web Component(LWC) with Jest library. In the next session, we will see how to test LWC with the different type of decorators.

6,477 total views, 6 views today

Posted in Lightning Components, Lightning Web Component | Leave a comment

DOM Manipulation in Lightning Web Component

In this session, we will learn how to manipulate DOM Tree in Lightning Web Component.

What is DOM?

  • The acronym of DOM is “Document Object Model”.
  • DOM is a programming API for HTML & XML.
  • DOM is a logical structure(tree) of the document.

When DOM is created?
At the time of loading HTML/XML, DOM is created.

Please see my video on youtube on regarding this DOM Manipulation in Lightning Web Component

 

 

To understand DOM Manipulation, we have created one Lightning Web Component (LWC) named “showContactsPanel” by which we can show the Contact records based on an account.

Please download this LWC from the following URL:

https://github.com/SantanuatGithub/DOMManipulation.git

According to the showContactsPanel.html file, DOM Tree looks like

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Generally, in HTML, we can access particular node with respect to Id, Class, Tag by using document.getElementById(“#Id”), document.getElementsByClassName(“.Class”), document.getElementsByTagName(“h1”) or by using this.document.querySelector().

To manipulate the DOM in LWC, we will use this.template.querySelector() where “template” is the root node in LWC.

Steps to execute

  • Deploy the downloaded “showContactsPanel” LWC with Apex Class.
  • Add this LWC into any Lightning Page and assign to any Lightning Application.
  • Need to focus on manipulateDOM() method in the JS file.
  • Uncomment the lines for the particular scenario just as mentioned in the Video. Please do not uncomment all the lines in this method.
  • Refresh the Page in Lightning Experience.
  • Click on “Check DOM” button to see the output. May be, browser console need to be opened to see the output for certain test cases.

 

//Read Header from lightning-card
console.log(‘Lightning Card Header–>’+this.template.querySelector(‘lightning-card’).title);
we can also use “main” class to get the title by using this.template.querySelector(‘.main’).title
//Change Title
this.template.querySelector(‘lightning-card’).title = “Learning DOM Manipulation in Lightning Web Component”;
//get text content
console.log(‘Content–>’+this.template.querySelector(‘.main’).textContent);
We can use textContent to get the value of a particular node.
//Change content color of the lightning-card
this.template.querySelector(‘lightning-card’).style.color=’green’;
//add same style from CSS file
this.template.querySelector(‘lightning-card’).classList.add(‘panelHeader’);
//get the contacts sequentially
let contactList = this.template.querySelectorAll(‘.conName’);
console.log(‘Contact 1–>’+contactList[0].textContent);
console.log(‘Contact 2–>’+contactList[1].textContent);
//get the length of the list
console.log(‘ConList–>’+contactList.length);
//change the color of last element
contactList[contactList.length-1].style.color=’red’;
//get first item
let firstItem = this.template.querySelector(‘.conName:first-child’);
console.log(‘firstChild–>’+firstItem.textContent);
//get last item
let lastItem = this.template.querySelector(‘.conName:last-child’);
console.log(‘lastChild–>’+lastItem.textContent);
//get nth Item
let nthConItem = this.template.querySelector(‘.conName:nth-child(2)’);
console.log(‘nthItem–>’+nthConItem.textContent);
//Stripped Table by DOM Execution
let contactOddList = this.template.querySelectorAll(‘.conName:nth-child(odd)’);
let contactEvenList = this.template.querySelectorAll(‘.conName:nth-child(even)’);
for(let i = 0; i < contactOddList.length; i++){
contactOddList[i].style.backgroundColor = ‘#D5DBDB’;
contactEvenList[i].style.backgroundColor = ‘#BDC3C7’;
}
//get the parent node
let contempList = this.template.querySelector(‘.contempList’);
console.log(‘parent node–>’+contempList.parentNode);
//get the parent node content
console.log(‘parent node–>’+contempList.parentNode.textcontent);
change the color of parent node
contempList.parentNode.style.color=”red”;
//get the child node
let parentContempList = this.template.querySelector(‘.parentContempList’);
console.log(‘child node–>’+parentContempList.children[0]);
//get the child node content
//console.log(‘child node–>’+parentContempList.children[0].textContent);
//change the color of child nodes
parentContempList.children[0].style.color=”green”;
parentContempList.children[1].style.color=”red”;
//set the child node contents
parentContempList.firstElementChild.textContent = “Displaying Data”;
parentContempList.lastElementChild.textContent = “Transferred Rows”;
//get attribute at certain level
letcontactList=this.template.querySelectorAll(‘.conName’);
for(let k=0; k<contactList.length; k++){
console.log(contactList[k].getAttribute(‘id’));
}
Q: Now, we want to see the Contact detail by clicking a button for every row. How can we achieve it?
If you open the “showContactsPanel” LWC, you can see entire second <tr> was commented in the table. Please uncomment this row and refresh the page. Now, you can see the specific Contact detail by clicking on each row.
We will analyze toggleRow() method in the JS file.
toggleRow(event){

        event.preventDefault();

        this.recId = event.target.dataset.id;
        
        //get the attribute of DOM element using wild characters
        //let currentElement = this.template.querySelector("[id^='" + this.recId + "']");
        //console.log('currentElement-->'+currentElement.textContent);

        
        this.recId = event.target.dataset.id;
        let conList = this.template.querySelectorAll('.conli');

        let btnList = this.template.querySelectorAll('.btn');

        for (let j = 0; j < btnList.length; j++){
            btnList[j].iconName = "utility:chevronright";
        }

        
        for (let i = 0; i < conList.length; i++){
            let indvRow = conList[i];
            let indvRowId = conList[i].getAttribute('id');  
            
            if(indvRowId.includes(this.recId)) {
                if(indvRow.classList.contains("slds-show")){
                    indvRow.classList.add("slds-hide");
                    indvRow.classList.remove("slds-show");
                    event.target.iconName = "utility:chevronright";
                }
                else{
                    indvRow.classList.remove("slds-hide");
                    indvRow.classList.add("slds-show");
                    event.target.iconName = "utility:chevrondown";
                }
            }
            else{
                indvRow.classList.add("slds-hide");
                indvRow.classList.remove("slds-show");
            }
        }
    }    
We have used data-id attribute in <lightning-button-icon> where data-id attribute contains the specific record id. If we want to get this record id on clicking, we have to use event.target.dataset just like event.target.dataset.id. After that, we need to compare the record id with the entire DOM to close the other rows’ panels and open the particular row panel for the specific Contact record just like
                                                                                    Thank you !!

 

 

6,113 total views, 4 views today

Posted in Lightning Web Component, Salesforce Lightning | Leave a comment

Showing Static Record using Apex to Wire Mechanism

Now, we will see how to get Salesforce data as static way using Apex.

We have built a LWC named “showWireApexStaticContact“.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record to Lightning Web Component. We can use the same class.

LWC_ContactController.cls

public with sharing class LWC_ContactController{
	@AuraEnabled(cacheable=true)
	public static Contact getStaticContact(){
		return [SELECT Id, Name, Title, Phone, Email FROM Contact LIMIT 1];
	}
}

getStaticContact() method returns the Contact Record.

Step 2: As per previous examples, we need to update the “showWireApexStaticContact.js-meta.xml” file to set the visibility in Lightning App Builder.

showWireApexStaticContact.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showWireApexStaticContact">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showWireApexStaticContact.html

<template>
        <lightning-card title="Showing Static Record (Wire * Apex)">            
            <lightning-layout> 
              <lightning-layout-item flexibility="auto" padding="around-small">
                   Contact
                   <template if:true={contactObj.data}> 
                        <div class="slds-m-around_medium">
                            <p>{name}</p>
                            <p>{phone}</p>
                            <p><lightning-formatted-email value={email}></lightning-formatted-email></p>
                        </div>
                    </template>
                    <template if:true={contactObj.error}>
                        {contactObj.error}>
                    </template>
              </lightning-layout-item>
            </lightning-layout>
        </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showWireApexStaticContact.js

import { LightningElement, wire } from 'lwc';
import { getSObjectValue } from '@salesforce/apex';
import getStaticContact from '@salesforce/apex/LWC_ContactController.getStaticContact';

import CONTACT_NAME_FIELD from '@salesforce/schema/Contact.Name';
import CONTACT_PHONE_FIELD from '@salesforce/schema/Contact.Phone';
import CONTACT_EMAIL_FIELD from '@salesforce/schema/Contact.Email';

export default class ShowStaticContact extends LightningElement {

    @wire(getStaticContact) contactObj;

    get name(){
        return this.contactObj.data
            ? getSObjectValue(this.contactObj.data, CONTACT_NAME_FIELD)
            : '';
    }

    get phone(){
        return this.contactObj.data
            ? getSObjectValue(this.contactObj.data, CONTACT_PHONE_FIELD)
            : '';
    }

    get email(){ 
        return this.contactObj.data
            ? getSObjectValue(this.contactObj.data, CONTACT_EMAIL_FIELD)
            : '';
    }
}

We have imported getSObjectValue from ‘@salesforce/apex’ and getStaticContact from our own Apex Class “LWC_ContactController” to get the Contact record.

In all getter functions(name.phone..), System will find out the specific field from the entire Contact Record by getSobjectValue() function.

Step 5: Need to add this component into Lightning App/Home or Record Page.

Result

3,688 total views, 9 views today

Posted in Lightning Web Component | Leave a comment

Showing Static Record using Apex to Imperative Mechanism

Now, we will see how to get Salesforce data as static way using Apex with Imperative way.

We have built a LWC named “showImperativeApexStaticContact“.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record to Lightning Web Component. We can use the same class.

LWC_ContactController.cls

public with sharing class LWC_ContactController{
	@AuraEnabled
	public static Contact getImperativeStaticContact(){
		return [SELECT Id, Name, Title, Phone, Email FROM Contact LIMIT 1];
	}
}

getImperativeStaticContact() method returns contact record. We have not set cacheable = true due to application of imperative mechanism.

Step 2: As per previous examples, we need to update the “showImperativeApexStaticContact.js-meta.xml” file to set the visibility in Lightning App Builder.

showImperativeApexStaticContact.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showImperativeApexStaticContact">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showImperativeApexStaticContact.html

<template>
        <lightning-card title="Showing Static Record (Imperative * Apex)">            
            <lightning-layout> 
              <lightning-layout-item flexibility="auto" padding="around-small">
                   Contact
                   <template if:true={contactObj}> 
                        <div class="slds-m-around_medium">
                            <p>{name}</p>
                            <p>{phone}</p>
                            <p><lightning-formatted-email value={email}></lightning-formatted-email></p>
                        </div>
                    </template>
                    <template if:true={error}>
                        {error}>
                    </template>
              </lightning-layout-item>
            </lightning-layout>
        </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showImperativeApexStaticContact.js

import { LightningElement, track } from 'lwc';
import { getSObjectValue } from '@salesforce/apex';
import getImperativeStaticContact from '@salesforce/apex/LWC_ContactController.getImperativeStaticContact';

import CONTACT_NAME_FIELD from '@salesforce/schema/Contact.Name';
import CONTACT_PHONE_FIELD from '@salesforce/schema/Contact.Phone';
import CONTACT_EMAIL_FIELD from '@salesforce/schema/Contact.Email';

export default class ShowImperativeApexStaticContact extends LightningElement {

    @track contactObj;
    @track error;

    connectedCallback(){
        getImperativeStaticContact()
        .then(result => {
            this.contactObj = result;
            this.error = undefined;
        }).catch(error=>{
            this.error = error;
            this.contactObj = undefined;
            
        })
    }
    

    get name(){
        return this.contactObj
            ? getSObjectValue(this.contactObj, CONTACT_NAME_FIELD)
            : '';
    }

    get phone(){
        return this.contactObj
            ? getSObjectValue(this.contactObj, CONTACT_PHONE_FIELD)
            : '';
    }

    get email(){
        return this.contactObj
            ? getSObjectValue(this.contactObj, CONTACT_EMAIL_FIELD)
            : '';
    }
}

In the imperative mechanism, we have set the contacts Private Reactive Property (during component creation time) to the contact record coming from the said Apex Class. Remaining process in same as wire mechanism.

Step 5: Need to add this component into Lightning App/Home or Record Page.

Result

3,187 total views, 3 views today

Posted in Lightning Web Component | Leave a comment

Apex Imperative Method with Parameters

Now, we will study how to get data based on some parameters from Lightning Platform Database using Imperative Way with Parameters in Lightning Web Component.

To do this exercise, we will show the Contact Records when user will click Search button after provided the Account Name.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record based on Account Name to Lightning Web Component. We can use the same class.

LWC_ContactController.cls

public with sharing class LWC_ContactController{
	@AuraEnabled
       public static List<Contact> searchImperativeContactList(String accountName){
           if (String.isBlank(accountName)) {
                return new List<Contact>();
            }
            String key = '%' + accountName + '%';
            return [SELECT Id, Name, Email FROM Contact WHERE Account.Name LIKE : key];
       }
}

searchImperativeContactList() method of the Apex Class “LWC_ContactController” returns the Contact Record based on Account Name. Please notice that we didn’t use cacheable = true for searchImperativeContactList() method just like wiring mechanism. That is the primary difference between wiring mechanism and imperative mechanism.

Step 2: After that, we have built a LWC named “showContactsIMP”. As per previous examples, we need to update the “showContactsIMP.js-meta.xml” file to set the visibility in Lightning App Builder.

showContactsIMP.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showContactsIMP">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showContactsWMP.html

<template>
    <lightning-card title="Apex Imperative Method With Parameters">            
        <lightning-layout>  
            <lightning-layout-item flexibility="auto" padding="around-small">        
                <lightning-layout-item flexibility="grow">
                    <lightning-input label="Enter Account Name" 
                                    type="search"  
                                    onchange={searchContact} 
                                    value={searchKey}>
                    </lightning-input>
                </lightning-layout-item>
                <lightning-layout-item class="slds-p-left_xx-small">
                    <lightning-button
                        label="Search"
                        onclick={doSearch}
                    ></lightning-button>
                </lightning-layout-item> 
                <lightning-layout-item class="slds-m-bottom_small">  
                    <template if:true={contacts}>                        
                        <template for:each={contacts} for:item="contact">                        
                            <p key={contact.Id}>                               
                                {contact.Name}
                            </p>
                        </template>
                    </template>
                    <template if:true={error}>
                        {error}>
                    </template>
                </lightning-layout-item>   
            </lightning-layout-item>              
        </lightning-layout>
      </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showContactsIMP.js

import { LightningElement, track } from 'lwc';
import searchImperativeContactList from '@salesforce/apex/LWC_ContactController.searchImperativeContactList';


export default class ShowContactsIMP extends LightningElement {

    @track contacts;
    @track error;

    searchContact(event){        
        this.searchKey = event.target.value;        
    }

    doSearch() {
        searchImperativeContactList({ accountName: this.searchKey })
            .then(result => {
                this.contacts = result;
                this.error = undefined;
            })
            .catch(error => {
                this.error = error;
                this.contacts = undefined;
            });
    }

}

As per the imperative mechanism writing rules, first we have imported “searchImperativeContactList” from the Apex Class, “LWC_ContactController”. We have built a function named “doSearch()” where the same adapter searchImperativeContactList() is invoked using javascript promise. We need to pass the parameter as Search Key/Account Name.Here, we don’t need to put ‘$’ sign before property during configuration of parameters. We have set the result to the respective reactive properties such as contacts and error.

We didn’t use cacheable = true for searchImperativeContactList() method as per imperative mechanism guide line.

Step 5: At last, need to add this LWC into Lightning App/Home or Record Page.

Result

15,862 total views, 39 views today

Posted in Lightning Web Component | Leave a comment

Apex Imperative Method

Already, we have studied how to get data from Lightning Platform Database using wire mechanism in Lightning Web Component. Now, we will study how to get data from Lightning Platform Database using Imperative Way in Lightning Web Component.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record to Lightning Web Component. We can use the same class.

LWC_ContactController.cls

public with sharing class LWC_ContactController{
	@AuraEnabled
	publicstaticList<Contact> getImperativeContactList(){
		return [SELECTId, Name, EmailFROMContactLIMIT1];
	}
}

getImperativeContactList() method of the Apex Class “LWC_ContactController” returns the Contact Record. Please notice that we didn’t use cacheable = true for getImperativeContactList() method just like wiring mechanism. That is the primary difference between wiring mechanism and imperative mechanism.

Step 2: After that, we have built a LWC named “showContactsIM“. As per previous examples, we need to update the “showContactsIM.js-meta.xml” file to set the visibility in Lightning App Builder.

showContactsIM.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showContactsIM">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showContactsIM.html

<template>
    <lightning-card title="Apex Imperative Method">            
        <lightning-layout>
          <lightning-layout-item flexibility="auto" padding="around-small">
               <template if:true={contacts}>                        
                    <template for:each={contacts} for:item="contact">                        
                        <p key={contact.Id}>                               
                            {contact.Name}
                            <lightning-formatted-email value={contact.Email} class="slds-m-left_medium"></lightning-formatted-email>
                        </p>
                    </template>
                </template>
                <template if:true={error}>
                    {error}
                </template>
          </lightning-layout-item>
        </lightning-layout>
      </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showContactsIM.js

import { LightningElement, track } from 'lwc';
import getImperativeContactList from '@salesforce/apex/LWC_ContactController.getImperativeContactList';

export default class ShowContactsIM extends LightningElement {
    @track contacts;
    @track error;

    connectedCallback(){ //you can build a method for a button
        getImperativeContactList()
        .then(result => {
            this.contacts = result;
            this.error = undefined;
        }).catch(error=>{
            this.error = error;
            this.contacts = undefined;
            
        })
    }
}

As per the imperative mechanism writing rules, first we have imported “getImperativeContactList” from the Apex Class, “LWC_ContactController”. Then, we have invoked a method with the same name of adapter which is getImperativeContactList() using javascript promise during component creation(connectedCallback()). We have set the result to the respective reactive properties such as contacts and error.

We didn’t use cacheable = true for getImperativeContactList() method as per imperative mechanism guide line.

Step 5: At last, need to add this LWC into Lightning App/Home or Record Page.

Result

11,886 total views, 21 views today

Posted in Lightning Web Component | Leave a comment

Imperative Service Syntax

We can get the Salesforce data in Lightning Web Component through Imperative Service.

Please see the following image carefully to understand the Imperative Service Methodology with Syntax.

 

2,752 total views, no views today

Posted in Lightning Web Component | Leave a comment

Apex Wire Method to Function with Parameters

Now, we will see how we can get the Salesforce Record details based on some parameters using Apex Class – Wiring to Function with Parameters mechanism. This mechanism is needed if you want to pre-process the data before going to the Lightning App.

To do this exercise, we will try to show a Contact Record based on Account Name in Lightning App.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record to Lightning Web Component. We can take the same Apex Class with the same method for this exercise as mentioned in the session “Apex Wire Method to Property with Parameters”.

LWC_ContactController.cls

public with sharing class LWC_ContactController{
        
      @AuraEnabled(cacheable = true)
       public static List<Contact> searchContactList(String accountName){
           if (String.isBlank(accountName)) {
                return new List<Contact>();
            }
            
            String key = '%' + accountName + '%';            
            return [SELECT Id, Name, Email FROM Contact WHERE Account.Name LIKE : key];
       }
}

Step 2: After that, we have built a LWC named “showContactsWMFP”. As per previous examples, we need to update the “showContactsWMFP.js-meta.xml” file to set the visibility in Lightning App Builder.

showContactsWMFP.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showContactsWMFP">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showContactsWMFP.html

<template>
        <lightning-card title="Apex Wire Method With Function Parameters">            
            <lightning-layout>
              <lightning-layout-item flexibility="auto" padding="around-small">
                    <lightning-input label="Enter Account Name" type="search"  onchange={searchContact} value={searchKey}></lightning-input>
                        <br/>
                        <template if:true={contacts}>                        
                            <template for:each={contacts} for:item="contact">                        
                                <p key={contact.Id}>                               
                                    {contact.Name}
                                </p>
                            </template>
                        </template>
                        <template if:true={error}>
                            {error}>
                        </template>                    
              </lightning-layout-item>
            </lightning-layout>
          </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showContactsWMFP.js

import { LightningElement, track, wire } from 'lwc';
import searchContactList from '@salesforce/apex/LWC_ContactController.searchContactList';

export default class ShowContactsWMFP extends LightningElement {
    @track searchKey = '';
    @track contacts;
    @track error;      

    searchContact(event){        
        this.searchKey = event.target.value;        
    }

    @wire(searchContactList, {accountName:'$searchKey'})
    wiredContacts({data, error}){
        if(data){
            this.contacts = data;
            this.error = undefined;
        }
        else if (error) {
            this.error = error;
            this.contacts = undefined;
        }
    }
}

As per the wire method writing rules, first we have imported “searchContactList” from the Apex Class, “LWC_ContactController“. Then, the function named wiredContacts is wired to searchContactList with parameters in this way
@wire(searchContactList, {accountName:’$searchKey’})
wiredContacts({data, error}){ }

where “searchkey” is the user input defines the Account Name. During passing of the parameters, we need to put ‘$’ sign before the property.

We have defined two private reactive properties such as contacts and error. We have set these two properties into the wired function named wiredContacts. Hence, we will get the Contact record details using only {contacts} instead of {contact.data} applied for wire method to property mechanism in HTML file. And obviously, we will get the errors using {error} in HTML file.

We have used wire mechanism so, the cacheable of the respective method, searchContactList() of the Apex Class “LWC_ContactController” should be true.

Step 5: At last, need to add this LWC into Lightning App/Home or Record Page.

Result

16,645 total views, 24 views today

Posted in Lightning Web Component | Leave a comment

Apex Wire Method to Function

Now, we will see how we can get the Salesforce Record details using Apex Class – Wiring to Function mechanism. This mechanism is needed if you want to pre-process the data before going to the Lightning App.

To do this exercise, we will try to show a Contact Record in Lightning App.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record to Lightning Web Component. We can take the same Apex Class with the same method for this exercise as mentioned in the session “Apex Wire Method to Property”.

LWC_ContactController.cls

1
2
3
4
5
6
7
public with sharing class LWC_ContactController{
       
       @AuraEnabled(cacheable = true)
       public static List<Contact> getContactList(){
           return [SELECT Id, Name, Email FROM Contact LIMIT 1];
       }
}

getContactList() method of the Apex Class “LWC_ContactController” returns the Contact Record.

Step 2: After that, we have built a LWC named “showContactsWMF“. As per previous examples, we need to update the “showContactsWMF.js-meta.xml” file to set the visibility in Lightning App Builder.

showContactsWMF.js-meta.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showContactsWMF">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showContactsWMF.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
        <lightning-card title="Apex Wire Method To Function">            
            <lightning-layout>
              <lightning-layout-item flexibility="auto" padding="around-small">
                   <template if:true={contacts}>                        
                        <template for:each={contacts} for:item="contact">                        
                            <p key={contact.Id}>                              
                                {contact.Name}
                                <lightning-formatted-email value={contact.Email} class="slds-m-left_medium"></lightning-formatted-email>
                            </p>
                        </template>
                    </template>
                    <template if:true={error}>
                        {error}>
                    </template>
              </lightning-layout-item>
            </lightning-layout>
          </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showContactsWMF.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { LightningElement, wire, track } from 'lwc';
import getContactList from '@salesforce/apex/LWC_ContactController.getContactList';

export default class ShowContactsWMF extends LightningElement {

    @track contacts;
    @track error;

    @wire(getContactList)
        wiredContacts({data, error}){
            if(data){
                this.contacts = data;
                this.error = undefined;
            }
            else if (error) {
                this.error = error;
                this.contacts = undefined;
            }
        }
}

As per the wire method writing rules, first we have imported “getContactList” from the Apex Class, “LWC_ContactController“. Then, the function named wiredContacts is wired to getContactList in this way
@wire(getContactList)
wiredContacts({data, error}){ }

We have defined two private reactive properties such as contacts and error. We have set these two properties into the wired function named wiredContacts. Hence, we will get the Contact record details using only {contacts} instead of {contact.data} applied for wire method to property mechanism in HTML file. And obviously, we will get the errors using {error} in HTML file.

We have used wire mechanism so, the cacheable of the respective method, getContactList() of the Apex Class “LWC_ContactController” should be true.

Step 5: At last, need to add this LWC into Lightning App/Home or Record Page.

Result

4,921 total views, 12 views today

Posted in Lightning Web Component | Leave a comment

Apex Wire Method to Property with Parameters

Now, we will see how we can get the Salesforce Record details based on some parameters using Apex Class – Wiring to Property with Parameters mechanism.

To do this exercise, we will try to search Contact Records based on Account Name in Lightning App.

Step 1: We have created an Apex Class named “LWC_ContactController” by which we will send the Contact record to Lightning Web Component based on Account Name. We can update the same Apex Class to consider the specific business.

LWC_ContactController.cls

public with sharing class LWC_ContactController{
       
      @AuraEnabled(cacheable = true)
       public static List<Contact> searchContactList(String accountName){
           if (String.isBlank(accountName)) {
                return new List<Contact>();
            }
           
            String key = '%' + accountName + '%';            
            return [SELECT Id, Name, Email FROM Contact WHERE Account.Name LIKE : key];
       }
}

searchContactList() method of the Apex Class “LWC_ContactController” returns the Contact Records based on Account Name.

Step 2: After that, we have built a LWC named “showContactsWMPP“. As per previous examples, we need to update the “showContactsWMPP.js-meta.xml” file to set the visibility in Lightning App Builder.

showContactsWMPP.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="showContactsWMP">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Step 3: Need to write the respective HTML file.

showContactsWMPP.html

<template>
        <lightning-card title="Apex Wire Method With Property Parameters">            
            <lightning-layout> 
              <lightning-layout-item flexibility="auto" padding="around-small">
                   <lightning-input label="Enter Account Name" type="search"  onchange={searchContact} value={searchKey}></lightning-input>
                    <template if:true={contacts.data}> 
                        <br/>                       
                        <template for:each={contacts.data} for:item="contact">                        
                            <p key={contact.Id}>                               
                                {contact.Name}
                            </p> 
                        </template>
                    </template>
                    <template if:true={contacts.error}>
                        {contacts.error}>
                    </template>
              </lightning-layout-item>
            </lightning-layout>
          </lightning-card>
</template>

Step 4: Now, we need to work on the JS file.

showContactsWMPP.js

import { LightningElement, track, wire } from 'lwc';
import searchContactList from '@salesforce/apex/LWC_ContactController.searchContactList';

const DELAY = 300;

export default class ShowContactsWMFP extends LightningElement {
    @track searchKey = '';
    
    @wire(searchContactList, {accountName:'$searchKey'}) contacts;

    searchContact(event){
        window.clearTimeout(this.delayTimeout);
        const searchKey = event.target.value;
        // eslint-disable-next-line @lwc/lwc/no-async-operation
        this.delayTimeout = setTimeout(() => {
            this.searchKey = searchKey;
        }, DELAY);
    }
}

As per the wire method writing rules, first we have imported “searchContactList” from the Apex Class, “LWC_ContactController“. Then, property contacts is wired to searchContactList with parameters in this way

@wire(searchContactList, {accountName:’$searchKey’}) contacts;  – where “searchkey” is the user input defines the Account Name. During passing of the parameters, we need to put ‘$’ sign before the property.

Remember, contacts is the property of wiring, that means we can get the data of contact using {contacts.data} & also we can get the error using {contacts.error} in html file and contacts is also the reactive property.

We have used wire mechanism so, the cacheable of the respective method, searchContactList() of the Apex Class “LWC_ContactController” should be true.

Here, we have defined searchContact(event) function to capture the Search Key as Account Name and set to the original searchKey property and wire adapter will automatically filtered out the Contact records based on Search Key. If the result is same, it will not make the server call.That is the beauty of Lightning web Component.

Step 5: At last, need to add this LWC into Lightning App/Home or Record Page.

Result

8,835 total views, 33 views today

Posted in Lightning Web Component | Leave a comment