LWC

Display and Update records using button in LWC:
 
Apex Class:

public  class AccountController 
{
   @AuraEnabled(cacheable=true)
   public static List<Account> displayAccounts(){
       return [select Id,Name,Site from Account];
   }
   @AuraEnabled
   public static List<Account> updateRecord(String accId){
       Account acc=[select Id,Name,Site from Account where Id=:accId];
       acc.site='Approved';
       try{
           update acc;
       }
   catch (Exception e) {
           System.debug('unable to update the record due to'+e.getMessage());
       }
       return displayAccounts();
   }
}

updateAccount.html

<template>
<table class="slds-table slds-table_cell-buffer slds-table_bordered">
<tr>
<td><b>Name</b></td>
<td><b>Site</b></td>
<td><b>Action</b></td>
</tr>
<template for:each={accounts.data} for:item="acc">
<tr key={acc.Id}>
<td>
{acc.Name}
</td>
<td>
{acc.Site}
</td>
<td>
<lightning-button label="update"  variant="brand" value={acc.Id} onclick={handleUpdate}>
</lightning-button>
</td>
</tr>
</template>
</table>
</template>
</template>

updateAccount.js

import { LightningElement,api,wire } from 'lwc';
import displayAccounts from '@salesforce/apex/AccountController.displayAccounts';
import updateRecord from '@salesforce/apex/AccountController.updateRecord';
import { refreshApex } from '@salesforce/apex';
export default class UpdateAccount extends LightningElement {
@api currentRecordId;
@api errorMessage;
    @wire(displayAccounts) accounts;
    handleUpdate(event){
        this.currentRecordId=event.target.value;
        console.log('@@currentRecordId@@@'+this.currentRecordId);
        updateRecord({
            accId:this.currentRecordId
        })
        .then(() => {
            console.log('SUCCESS');
            return refreshApex(this.accounts);
        })
        .catch((error) => {
            this.errorMessage=error;
console.log('unable to update the record due to'+JSON.stringify(this.errorMessage));
        });
    }
}

LightningApplication

<aura:application extends="force:slds">
<c:updateAccount/>
</aura:application>


___________________________________________________________


LWC Search Page:





Wire an Apex Method with a Dynamic Parameter

Now let’s wire an Apex method that takes a parameter. 


// ContactController.cls

public with sharing class ContactController {    
    @AuraEnabled(cacheable=true)
    public static List<Contact> findContacts(String searchKey) {
        String key = '%' + searchKey + '%';
        return [
            SELECT Id, Name, Title, Phone, Email, Picture__c
            FROM Contact
            WHERE Name LIKE :key AND Picture__c != null
            WITH SECURITY_ENFORCED
            LIMIT 10
        ];
    }
}

The component’s JavaScript prefaces the value of the searchKey parameter with $ to indicate that it’s dynamic and reactive. It references a property of the component instance. If its value changes, the template rerenders.

Important
IMPORTANT To @wire the component to the Apex method, the first parameter is a string, which is the name of the Apex method—in this case, findContacts. The second @wire parameter is an object that contains the parameters to pass to the Apex method. So, for example, even though findContacts takes a string, we don’t pass a string as the second @wire parameter. Instead, we pass an object that contains a property whose value is a string: { searchKey: '$searchKey' }. (If the Apex method took another parameter, we would add another property to the object.)

// apexWireMethodWithParams.js
import { LightningElement, wire } from 'lwc';
import findContacts from '@salesforce/apex/ContactController.findContacts';

/** The delay used when debouncing event handlers before invoking Apex. */
const DELAY = 300;

export default class ApexWireMethodWithParams extends LightningElement {
    searchKey = '';

    @wire(findContacts, { searchKey: '$searchKey' })
    contacts;

    handleKeyChange(event) {
        // Debouncing this method: Do not update the reactive property as long as this function is
        // being called within a delay of DELAY. This is to avoid a very large number of Apex method calls.
        window.clearTimeout(this.delayTimeout);
        const searchKey = event.target.value;
        this.delayTimeout = setTimeout(() => {
            this.searchKey = searchKey;
        }, DELAY);
    }
}

The template uses searchKey as the value of the <lightning-input> field.

<!-- apexWireMethodWithParams.html -->

<template>
    <lightning-card title="ApexWireMethodWithParams" icon-name="custom:custom63">
        <div class="slds-m-around_medium">
            <lightning-input type="search" onchange={handleKeyChange} class="slds-m-bottom_small" label="Search" value={searchKey}></lightning-input>
            <template if:true={contacts.data}>
                <template for:each={contacts.data} for:item="contact">
                    <p key={contact.Id}>{contact.Name}</p>
                </template>
            </template>
            <template if:true={contacts.error}>
                <c-error-panel errors={contacts.error}></c-error-panel>
            </template>
        </div>
    </lightning-card>
</template>

____________________________________________________________


Wire an apex method to a property:
==========================

Apex Controller:

public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List<Contact> getContactList() {
return [SELECT ID, Name, Phone FROM Contact 
WITH SECURITY_ENFORCED LIMIT 10];
}
}


Javascript:

import {LightningElement, wire} from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class ApexWireMethodToProperty extends LightningElement {
@wire(getContactList) contacts;
}

HTML TEMPLATE:

<template>
<lightning-card title="ApexWireMethodToProperty" icon-name="custom:custom63" >
<div class="slds-m-around-medium">
<template if:true={contacts.data}>
<template for:each={contacts.data} for:item="contact">
<p key={contact.Id}> {contact.Name} </p>
</template>
</template>
</div>
</lightning-card>
</template>



Wire an Apex Method with a Dynamic Parameter:
=====================================

Apex Controller:
===========

public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List<Contact> findContacts(String searchKey){
String key = '%' + searchKey + '%';
return [SELECT Id, Name, Phone FROM Contact WHERE Name LIKE :key 
WITH SECURITY_ENFORCED LIMIT 10 ];
}
}


Javascript:
=======

import {LightningElement, wire} from 'lwc';
import findContacts from '@salesforce/apex/ContactController.findContacts';

const DELAY = 300;

export default class ApexWireMethodWithParams extends LightningElement {
    searchKey = '';

    @wire(findContacts, { searchKey: '$searchKey' })
    contacts;

    handleKeyChange(event) {
        window.clearTimeout(this.delayTimeout);
        const searchKey = event.target.value;
        this.delayTimeout = setTimeout(() => {
            this.searchKey = searchKey;
        }, DELAY);
    }
}

TEMPLATE:
========

<!-- apexWireMethodWithParams.html -->
<template>
    <lightning-card title="ApexWireMethodWithParams" icon-name="custom:custom63">
        <div class="slds-m-around_medium">
            <lightning-input type="search" onchange={handleKeyChange} class="slds-m-bottom_small" label="Search" value={searchKey}></lightning-input>
            <template if:true={contacts.data}>
                <template for:each={contacts.data} for:item="contact">
                    <p key={contact.Id}>{contact.Name}</p>
                </template>
            </template>
            <template if:true={contacts.error}>
                <c-error-panel errors={contacts.error}></c-error-panel>
            </template>
        </div>
    </lightning-card>
</template>


Call Apex Methods Imperatively:
========================

public with sharing class ContactController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContactList() {
        return [
            SELECT Id, Name, Title, Phone, Email, Picture__c
            FROM Contact
            WHERE Picture__c != NULL
            WITH SECURITY_ENFORCED
            LIMIT 10
        ];
    }
}


// apexImperativeMethod.js
import { LightningElement, track } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

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

    handleLoad() {
        getContactList()
            .then(result => {
                this.contacts = result;
            })
            .catch(error => {
                this.error = error;
            });
    }
}

<template>
    <lightning-card title="ApexImperativeMethod" icon-name="custom:custom63">
        <div class="slds-m-around_medium">
            <p class="slds-m-bottom_small">
                <lightning-button label="Load Contacts" onclick={handleLoad}></lightning-button>
            </p>
            <template if:true={contacts}>
                <template for:each={contacts} for:item="contact">
                    <p key={contact.Id}>{contact.Name}</p>
                </template>
            </template>
            <template if:true={error}>
                <c-error-panel errors={error}></c-error-panel>
            </template>
        </div>
    </lightning-card>
</template>


Call an Apex Method imperatively with Parameters:
=======================================

public with sharing class ContactController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> findContacts(String searchKey) {
        String key = '%' + searchKey + '%';
        return [
            SELECT Id, Name, Title, Phone, Email, Picture__c
            FROM Contact
            WHERE Name LIKE :key AND Picture__c != NULL
            WITH SECURITY_ENFORCED
            LIMIT 10
        ];
    }
}


import { LightningElement } from 'lwc';
import findContacts from '@salesforce/apex/ContactController.findContacts';

export default class ApexImperativeMethodWithParams extends LightningElement {
    searchKey = '';
    contacts;
    error;

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

    handleSearch() {
        findContacts({ searchKey: this.searchKey })
            .then((result) => {
                this.contacts = result;
                this.error = undefined;
            })
            .catch((error) => {
                this.error = error;
                this.contacts = undefined;
            });
    }
}


=======================================================================

LWC Tutorial:

 

Lightning web components are custom HTML elements built using HTML and modern JavaScript.

 

LWC is lightweight and has amazing performance.

 

DOM stands for Document Object Model. It is a programming interface that allows us to create, change, or remove elements from the document.

Shadow DOM: Shadow DOM serves for encapsulation.

 

Lightning Web Component Example:

============================

 

helloLwc.js:

------------

import { LightningElement } from 'lwc';

export default class HelloLwc extends LightningElement {

    welcomeMessage = "Hey! Welcome to SalesforceBlue :)"

}

 

helloLwc.html:

--------------

<template>

    <lightning-card>

        <p class="slds-p-horizontal_small">

            {welcomeMessage}

        </p>

    </lightning-card>

</template>

 

helloLwc.js-meta.xml:

---------------------

<?xml version="1.0" encoding="UTF-8"?>

<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">

    <apiVersion>55.0</apiVersion>

    <isExposed>true</isExposed>

    <targets>

        <target>lightning__AppPage</target>

        <target>lightning__RecordPage</target>

        <target>lightning__HomePage</target>

    </targets>

</LightningComponentBundle>

 

Lightning Web Component Decorators:

==============================

The Lightning Web Components programming model has three decorators that add functionality to property or function.

 

@api: To expose a public property, decorate it with @api. Public properties define the API for a component. Public properties are reactive. If the value of reactive property changes, the component’s template rerenders any content that references the property.

 

@track: To track a private property’s value and rerender a component when it changes, decorate the property with @track. Tracked properties are private reactive properties.

 

@wire: To read Salesforce data, Lightning web components use a reactive wire service. When the wire service provisions data, the component rerenders. Components use @wire in their JavaScript class to specify a wire adaptor or an Apex method.

 

Lightning Web Component Lifecycle hooks:

=============================

constructor(): The constructor() method fires when a component instance is created.

 

connectedCallback() and disconnectedCallback(): The connectedCallback() lifecycle hook fires when a component is inserted into the DOM. The disconnectedCallback() lifecycle hook fires when a component is removed from the DOM.

 

Both connectedCallback() and disconnectedCallback() lifecycle hooks flows from parent to child.

 

renderedCallback(): The renderedCallback() lifecycle hook fires after a component has finished the rendering phase. This lifecycle hooks flows from child to parent.

 

errorCallback(): errorCallback() captures errors that occur in the descendant’s lifecycle hooks or during an event handler declared in an HTML template.

 

 

Referring to Lightning Web Component Inside A Parent Component (LWC):

Camel case component folder names map to kebab-case in markup. In this post, we have created the component folder name as helloLwc so to reference this component inside a parent lwc component, use <c-hello-lwc>. Here c is the default namespace.

 

<-- parentLwc.html -->

<template>

    <c-hello-lwc></c-hello-lwc>

</template>

 

Communicating From Child To Parent In LWC:

==============================

A child component can dispatch a custom event which will be handled by the parent component. Let’s understand this by the below example:

 

Dynamic search functionality in Lightning Web Component with event

public with sharing class AccountDataController {

    public AccountDataController() {

    }

    @AuraEnabled

    public static List<Account> displayAccounts(String searchekey){

        String searchword='%'+searchekey+'%';

        List<Account> returnlist=new List<Account>();

        if(!String.isBlank(searchekey))

        for(Account acc:[select Id,Name,Site from Account where Name like:searchword]){

            returnlist.add(acc);

        }

        return returnlist;

    }

}

searchAccountComponent.html èchild component

<template>

    <lightning-input type="text"  class="accName" label="SearchAccounts" onchange={handleSearch}>

    </lightning-input>

</template>

 

searchAccountComponent.js

import { LightningElement,api } from 'lwc';

 

export default class SearchAccountComponent extends LightningElement {

   

    @api userInput;

    handleSearch(event){

        this.userInput=event.target.value;

        const newEvent=new CustomEvent('inputcarryevent',{

            detail:this.userInput

 

        });

        this.dispatchEvent(newEvent);

    }   }

 

accountDataComponent.html èparent component

<template>

    <c-search-account-component oninputcarryevent={displayData}>

    </c-search-account-component><br/><br/>

    <div if:true={isshow}>

        <table class="slds-table slds-table_cell-buffer slds-table_bordered">

            <tr>

                <td><b>Name</b></td>

                <td><b>Site</b></td>

            </tr>

            <template for:each={records} for:item="acc">

                <tr key={acc.Id}>

                    <td>

                        {acc.Name}

                    </td>

                    <td>   {acc.Site}

                    </td></tr></template>

        </table>

    </div>

</template>

accountDataComponent.js

import { LightningElement,api } from 'lwc';

import displayAccounts from '@salesforce/apex/AccountDataController.displayAccounts';

 

export default class AccountDataComponent extends LightningElement {

    @api records;

    @api error;

    @api isshow;

    displayData(event){

        console.log('@@@@Entered into the method@@@');

        displayAccounts({

            searchekey:event.detail

        })

        .then(result=>{

            this.records=result;

            console.log('@@@records'+JSON.stringify(this.records));

            if(result.length!=0){

                this.isshow=true;

            }

            else{

                this.isshow=false;

            }

            this.error=undefined;

 

        })

        .catch(error=>{

            this.records=undefined;

            this.error=error;

        });

    } }

 

LightningApplication

<aura:application extends="force:slds" >

    <c:accountDataComponent/>

</aura:application>

 

 

Communicating From Parent To Child In LWC:

Decorate a method with @api in the child component to allow a parent component to call methods in the child component. Let’s understand this with the below example.

 

We would be updating the childLwc and parentLwc components created above for this example.

 

Add the following code in childLwc component:

 

import { LightningElement, api } from 'lwc';

export default class ChildLwc extends LightningElement {

    message;

    @api greet(message) {

        // Suppose a translating capability is here which translate the message param to local user's language

        this.message = message;

    }

}

At Line 8 in the above code, we have decorated the greet method with @api so that it is publically available to be called from the parent component.

 

 

<template>

    <lightning-card title="Child LWC">

        <p class="slds-p-horizontal_small">

            Message In Child Component : {message}

        </p>

    </lightning-card>

</template>

Add the following code in parentLwc component:

 

 

<template>

    <lightning-card title="Parent LWC">

        <lightning-button variant="brand" label="Send Message" title="Send Message" slot = "actions" onclick={parentHandler}></lightning-button>

        <c-child-lwc onsendmessage={parentHandler}></c-child-lwc>

    </lightning-card>

</template>

 

import { LightningElement } from 'lwc';

 

export default class ParentLwc extends LightningElement {

 

    parentHandler(event) {

        this.template.querySelector('c-child-lwc').greet('Hey, This Message Is Sent From Parent!');

    }

 

}

In the above code, we are calling the child method by using this.template.querySelector(‘c-child-lwc’)

 

querySelector() returns the first Element within the document that matches the specified selector.

 

View the parentLwc component on the lightning app page, you would be getting the below output:

 

 

 

 

Display and Update records using button in LWC:

 

Apex Class:

public  class AccountController 
{
   @AuraEnabled(cacheable=true)
   public static List<Account> displayAccounts(){
       return [select Id,Name,Site from Account];
   }
   @AuraEnabled
   public static List<Account> updateRecord(String accId){
       Account acc=[select Id,Name,Site from Account where Id=:accId];
       acc.site='Approved';
       try{
           update acc;
       }
                  catch (Exception e) {
           System.debug('unable to update the record due to'+e.getMessage());
       }
       return displayAccounts();
   }
}

updateAccount.html

<template>
               <table class="slds-table slds-table_cell-buffer slds-table_bordered">
                              <tr>
                                             <td><b>Name</b></td>
                                             <td><b>Site</b></td>
                                             <td><b>Action</b></td>
                              </tr>
                              <template for:each={accounts.data} for:item="acc">
                                             <tr key={acc.Id}>
                                                            <td>
                                                                           {acc.Name}
                                                            </td>
                                                            <td>
                                                                           {acc.Site}
                                                            </td>
                                                            <td>
                                                                           <lightning-button label="update"  variant="brand" value={acc.Id} onclick={handleUpdate}>
                                                                           </lightning-button>
                                                            </td>
                                             </tr>
                              </template>
               </table>
</template>
</template>


updateAccount.js

import { LightningElement,api,wire } from 'lwc';
import displayAccounts from '@salesforce/apex/AccountController.displayAccounts';
import updateRecord from '@salesforce/apex/AccountController.updateRecord';
import { refreshApex } from '@salesforce/apex';
export default class UpdateAccount extends LightningElement {
               @api currentRecordId;
               @api errorMessage;
    @wire(displayAccounts) accounts;
    handleUpdate(event){
        this.currentRecordId=event.target.value;
        console.log('@@currentRecordId@@@'+this.currentRecordId);
        updateRecord({
            accId:this.currentRecordId
        })
        .then(() => {
            console.log('SUCCESS');
            return refreshApex(this.accounts);
        })
        .catch((error) => {
            this.errorMessage=error;
                                             console.log('unable to update the record due to'+JSON.stringify(this.errorMessage));
        });
    }
}

LightningApplication

<aura:application extends="force:slds">
               <c:updateAccount/>
</aura:application>

 

 

 

No comments:

Post a Comment