Thursday, May 4, 2023

Communicating Across the DOM with Lightning Message Service

 

Use Lightning message service to communicate across the DOM within a Lightning page. Communicate between Visualforce pages embedded in the same Lightning page, Aura components, and Lightning web components, including components in a utility bar and pop-out utilities. Choose whether a component subscribes to messages from the entire application, or from only the active area.

If you're switching from Salesforce Classic to Lightning Experience, you can build Lightning web components that can communicate with existing Visualforce pages or Aura components. You can also use Lightning message service to communicate with softphones via Open CTI.

Important

Lightning message service is available in Lightning Experience and as a beta feature for Lightning components used in Experience Builder sites.

To access Lightning message service in Aura, use the lightning:messageChannel component. A message is a serializable JSON object. Examples of data that you can pass in a message include strings, numbers, booleans, and objects. A message can’t contain functions and symbols. The lightning:messageChannel component is only available in Lightning Experience.

Wednesday, May 3, 2023

Display Contacts with Account detail Table In LWC

Apex Class :

public with sharing class AccountsAndContactsTabelLWCCtr {
    public AccountsAndContactsTabelLWCCtr() {
       
    }
    @AuraEnabled(cacheable=true)
    public static List<contact> getAccsAndCons(){
        try {
            return [select id, Name, Email, Accountid, Account.Name from contact where email != null limit 20 ];
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }
}

meta.xml:

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

JS :

import { LightningElement ,api, wire, track} from 'lwc';
import getAccsCons from '@salesforce/apex/AccountsAndContactsTabelLWCCtr.getAccsAndCons'

const columns = [
    { label: 'Contact Name', fieldName: 'Name' },
    { label: 'Contact Email', fieldName: 'Email' },
    { label: 'Account Name', fieldName: 'AccName' }
];
export default class AccountsAndContactsTabelLWC extends LightningElement {
    @api recordId;
    @track records;
    @track dataNotFound;
    columns = columns;
    @wire (getAccsCons)
    wireRecord({data,error}){
        if(data){
            let tempRecords = JSON.parse( JSON.stringify( data ) );
            console.log('tempRecords : '+tempRecords);
            tempRecords = tempRecords.map( row => {
                console.log('Email : '+row.Email);
                return {Name: row.Name,Email: row.Email, AccName: ( row.Account ? row.Account.Name : null ) };
            })
           
            this.records = tempRecords;
            console.log('Data : '+tempRecords);
            this.error = undefined;
            this.dataNotFound = '';
            if(this.records == ''){
                this.dataNotFound = 'There is no Contact found related to Account name';
            }
 
           }else{
               this.error = error;
               this.data=undefined;
           }
    }
   
}

 HTML:

<template>
    <lightning-card variant="narrow" icon-name="standard:account" title="Contacts">
        <lightning-datatable
                key-field="Id"
                data={records}
                columns={columns}
                hide-checkbox-column="false">
        </lightning-datatable>
    </lightning-card>
</template>

Decorators in Lightning Web Component

 

What Are Decorators In Lightning Web Component?

A Decorator is a design pattern that allows adding behaviors to Javascript Objects. Decorators which are part of ECMAScript are used to dynamically alter or modify the functionality.

Type Of Decorators In Lightning Web Component

There are three types of Decorators in Lightning web components.

  1. API
  2. Track
  3. Wire

Let's see them in detail.

1. @api

To expose a public property or a public method, decorate with @api. Public properties are reactive, also known as public reactive properties since if the value of property changes then the component is re-rendered

  • Public properties define the API of a component whereas public methods are part of a component’s API
  • A Component is re-rendered when the value of a referenced public property is modified or changed
  • To pass data from the parent component to the child component, the @api decorator in the child component exposes a property by making it public so that the parent component can update it
  • @api properties can be exposed in an App builder

Please find the below code snippet that provides an insight into how an @api property on a child component is set from a parent component:

apiDecoratorSampleChildComponent.html

<template>
    <lightning-card title="Child Component">
        <div class="slds-p-around_medium">
            <p class="slds-p-horizontal_small">{message}</p>
        </div>
    </lightning-card>
</template>

apiDecoratorSampleChildComponent.js

import { LightningElement, api } from 'lwc';
 
export default class ApiDecoratorSampleChildComponent extends LightningElement {
    @api message;
}

apiDecoratorSampleChildComponent.js-meta.xml

apiDecoratorSampleParentComponent.html

<template>
    <c-api-decorator-sample-child-component message = 'Message From Parent Component!!'></c-api-decorator-sample-child-component>
</template>

apiDecoratorSampleParentComponent.js

import { LightningElement } from 'lwc';
 
export default class ApiDecoratorSampleParentComponent extends LightningElement {}

2. @track

To expose private property or a private method, declare with @track. Also known as Private reactive properties

  • To track a private property and to re-render a component when that property changes, use @track decorator (Available only for the component where it is declared)
  • Fields that are using @track decorator that contains an object or an array, tell the framework to observe changes to the properties of an object or elements of an array
  • After Salesforce Spring ’20, all the fields in a Lightning Web Component are reactive. If a field is used in a template & value changes, the component re-renders and displays a new value by default

helloWorld.html

<template>
    <lightning-card title="Hello World" icon-name="custom:custom14">
      <div class="slds-m-around_medium">
        <p>Hello, {greetingMessage}!</p>
        <lightning-input label="Name" value={greeting} onchange={changeHandler}></lightning-input>
      </div>
    </lightning-card>
  </template>

helloWorld.js

import { LightningElement } from 'lwc';
export default class HelloWorld extends LightningElement {
  //@track greetingMessage = 'World';//Before Spring ’20 to need to import track decorator & use it to make a field reactive
  greetingMessage = 'World';
 
  changeHandler(event) {
    this.greetingMessage = event.target.value;
  }
}

3. @wire

  • Reactive wire service is utilized in Lightning Web Components to read the Salesforce data from the apex class into Lightning Web Components
  • A component is re-rendered when wire service provisions the data from the apex class. The output from the apex method is set to a property

Syntax:

import <methodName> from ‘@salesforce/apex/<Namespace.ApexClassName.apexMethod>’;

@wire(methodName, {methodParams})

propertyOrFunction;

methodName: A variable that identifies the Apex method. 

apexMethod: The name of the Apex method to import. 

ApexClassName: The name of the Apex class. 

Namespace: Defines the namespace of the Salesforce organization. Only specify a namespace when the organization doesn’t use the default namespace (c)

displayContacts.html

<template>
    <lightning-card title="Contacts" icon-name="standard:contact_list">
        <div class="slds-m-around_medium">
            <template if:true={contacts.data}>
                <template for:each={contacts.data} for:item="con">
                    <p key={con.Id}>{con.Name}</p>
                </template>
            </template>
        </div>
    </lightning-card>
 </template>

displayContacts.js

import { LightningElement, wire } from 'lwc';
import getContactsList from '@salesforce/apex/ContactsService.getContacts';
 
export default class DisplayContacts extends LightningElement {
 
    @wire(getContactsList) //Wiring the Output of Apex method to a property
    contacts;
}

Tuesday, May 2, 2023

Static, final, this, super keywords in apex

 static

This keyword defines a method/variable that is only initialized once and is associated with an (outer) class, and initialization code. We can call static variables/methods by class name directly. No need of creating an instance of a class.

Static variables are variables that belong to an overall class, not a particular object of a class. Think of a static variable to be like a global variable – its value is shared across your entire org. Any particular object’s properties or values are completely irrelevant when using static.

Static methods, similarly, are methods that act globally and not in the context of a particular object of a class. Being global, static methods only have access to their provided inputs and other static (global) variables.

Example

public class OuterClass {

	// Associated with instance
	public static final Integer MY_INT;
	
	// Initialization code
	static {
	MY_INT = 10;
	}
	
}

final

This keyword is used to define constants and methods that can’t be overridden.

Example

public class myCls {
    static final Integer INT_CONST;
}

this

This keyword represents the current instance of a class, in constructor chaining.

Example

public class Foo {
	
	public Foo(String s) {/* … */}
	
	public foo() {
	
	this('memes repeat'); }
	
}

super

This keyword invokes a constructor on a superclass.

Example

public class AnotherChildClass extends InnerClass {
	AnotherChildClass(String s) {
		super();
		// different constructor, no args
	}
}

return

This keyword returns a value from a method.

Example

public Integer sum() {
    return int_var;
}

transient

This keyword declares instance variables that cannot be saved, and should not be transmitted as part of the view state, in Visualforce controllers and extensions.

Example

transient integer currentValue;

null

This keyword defines a null constant that can be assigned to any variable.

Example

Boolean b = null;

Like other programming languages, there are many other keywords in Apex programming language. We will see those in other posts.

Tuesday, March 8, 2022

LWC Display List of Cases in Table

 HTML : 

<!--

 * @File Name          : LWC_CaseLWCService.cls

 * @Description        : 

 * @Author             : Venkataramana D

 * @Group              : 

 * @Last Modified By   : Venkataramana D

 * @Last Modified On   : 28/FEB/2022, 1:54:34 pm

 * @Modification Log   : 

 * Ver       Date            Author          Modification

 * 1.0    28/FEB/2022   Venkataramana D     Initial Version

-->

<template>

    Testing:

    <lightning-card  variant="Narrow"  title="Case List" icon-name="standard:case">

        <div class="slds-m-around_small">

            <lightning-datatable

                key-field="id"

                data={result}

                show-row-number-column

                hide-checkbox-column

                columns={columnsList}

                onrowaction={handleRowAction}>

            </lightning-datatable>

        </div>

    </lightning-card>

</template>

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

JS:

import { LightningElement, wire, api, track } from 'lwc';

import fetchCases from '@salesforce/apex/LWC_CaseLWCService.fetchCases';


const columns = [

    { 

        label: 'CaseNumber', fieldName: 'caseUrl', type:'url',

        typeAttributes: {

            label: { 

                fieldName: 'CaseNumber' 

            },

            target : '_blank'

        }

    },

    { 

        label: 'Subject', fieldName: 'subjectUrl', wrapText: true,

        type: 'url',

        typeAttributes: {

            label: { 

                fieldName: 'Subject' 

            },

            target : '_blank'

        }

    },

    { label: 'Status', fieldName: 'Status' },

    {

        label: 'Priority', fieldName: 'Priority',

        cellAttributes:{ 

            iconName: { 

                fieldName: 'priorityIcon' 

            },

            iconPosition: 'left', 

            iconAlternativeText: 'Priority Icon' 

        }

    },

    { 

        label: 'Contact', fieldName: 'ContactUrl', wrapText: true,

        type: 'url',

        typeAttributes: {

            label: { 

                fieldName: 'ContactName' 

            },

            target : '_blank'

        } 

    },

    { 

        label: 'Account', fieldName: 'AccountUrl', wrapText: true,

        type: 'url',

        typeAttributes: {

            label: { 

                fieldName: 'AccountName' 

            },

            target : '_blank'

        } 

    }

];



            


export default class LWC_CaseDatatable extends LightningElement {

    

    @api result;

    @track error;


    columnsList = columns;

    

    connectedCallback(){

        this.getAllCaseDetails();

    }


    getAllCaseDetails(){

        fetchCases()

            .then(data => {

                /* Iterate with Each record and check if the Case is Associated with Account or Contact

                    then get the Name and display into datatable

                */

                /* Prepare the Org Host */

                let baseUrl = 'https://'+location.host+'/';

                data.forEach(caseRec => {

                    caseRec.caseUrl = baseUrl+caseRec.Id;

                    if(caseRec.Subject==null){

                        caseRec.subjectUrl  = null;

                    }else {

                        caseRec.subjectUrl = baseUrl+caseRec.Id;

                    }

                    if(caseRec.ContactId){

                        caseRec.ContactName = caseRec.Contact.Name;

                        /* Prepare Contact Detail Page Url */

                        caseRec.ContactUrl = baseUrl+caseRec.ContactId;

                    }

                    if(caseRec.AccountId){

                        caseRec.AccountName = caseRec.Account.Name;

                        /* Prepare Account Detail Page Url */

                        caseRec.AccountUrl = baseUrl+caseRec.AccountId;

                    }


                    if(caseRec.Priority === 'High'){

                        caseRec.priorityIcon = 'utility:log_a_call';

                    } else if (caseRec.Priority === 'Medium'){

                        caseRec.priorityIcon = 'utility:note';

                    } else if(caseRec.Priority === 'Low'){

                        caseRec.priorityIcon = 'utility:open';

                    }

                });

                this.result = data;

                window.console.log(' data ', data);

                this.error = undefined;

            })

            .catch(error => {

                this.error = error;

                window.console.log(' error ', error);

                this.result = undefined;

            });

    }

    

    handleRowAction(){

        

    }

}

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

Meta.XML

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

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

    <apiVersion>52.0</apiVersion>

    <isExposed>true</isExposed>

    <targets>

        <target>lightning__AppPage</target>

        <target>lightning__RecordPage</target>

        <target>lightning__HomePage</target>

      </targets>

</LightningComponentBundle>

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

APex Class :

/**

 * @File Name          : CaseLWCService.cls

 * @Description        : 

 * @Author             : Venkataramana D

 * @Group              : 

 * @Last Modified By   : Venkataramana D

 * @Last Modified On   : 28/FEB/2022, 1:54:34 pm

 * @Modification Log   : 

 * Ver       Date            Author          Modification

 * 1.0    28/FEB/2022   Venkataramana D     Initial Version

**/

public with sharing class LWC_CaseLWCService {

    public LWC_CaseLWCService() {


    }


    @AuraEnabled

    public static List<Case> fetchCases(){

        return [SELECT Id, CaseNumber, Subject, Description, AccountId, Account.Name, ContactId,

                Contact.Name, Status, Priority FROM CASE LIMIT 10];

    }

}