Apex Class :
meta.xml:
JS :
HTML:
Apex Class :
meta.xml:
JS :
HTML:
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.
There are three types of Decorators in Lightning web components.
Let's see them in detail.
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
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 {}

To expose private property or a private method, declare with @track. Also known as Private reactive properties
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;
}
}
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;
}
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;
}
}This keyword is used to define constants and methods that can’t be overridden.
Example
public class myCls {
static final Integer INT_CONST;
}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'); }
}This keyword invokes a constructor on a superclass.
Example
public class AnotherChildClass extends InnerClass {
AnotherChildClass(String s) {
super();
// different constructor, no args
}
}This keyword returns a value from a method.
Example
public Integer sum() {
return int_var;
}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;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.
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];
}
}
Platform Event is based on Event-Driven Architecture which enable apps to communicate inside and outside of Salesforce. Platform events are based on the publish/subscribe model and work directly with a message bus which handles the queue of incoming events and processes listening for them. This is built in real time integration patterns in the Salesforce Platform which helps to reduce point-to-point integration
SObjects__c | Platform_Events__e |
DMLs (Insert, Update, Delete) | Publish (Insert only) |
SOQL | Streaming API |
Triggers | Subscribers |
Parallel context execution | Guaranteed order of execution |
Introduction:
Platform Events are used to deliver secure, scalable, and customizable notification within Salesforce or external app. Platform Event is based on Event-Driven Architecture. This is built in real time integration patterns in the Salesforce Platform which helps to reduce point-to-point integration.
Publishing platform event:
We can publish the platform events in 3 ways:
Not supported in Platform event:
Subscription in Platform Event:
Defining Objects and fields in Platform Events:
Platform events can be created just like the custom objects. The biggest difference between Platform events and Custom object is suffix name for the api name. In Platform events, its api name suffix with __e where the custom object appends __c suffix to create api name. Unlike with custom objects, we cannot update or delete event record, or view event records in Salesforce User Interface.
Platform Events support only following custom fields type,
ReplayId System Field and Event Retention
Steps to Create and Publish Platform Events:




NotificationController.cls

helpNotification.cmp:

helpNotificationController.js

helpNotificationHelper.js


v




Conclusion:
It is no longer applications are pulling out from multiple endpoints and polling to retrieve the data. We can get the data by subscribing to the platform event. It will help create 360-degree customer experience to get the information when the data changes.
----------------------------------------------------------------------------------------------------------------------
Salesforce event-driven architecture is consisting of
Platform events simplify the process of communicating changes and responding to events. Publishers and subscribers communicate with each other through events. One or more subscribers can listen to the same event and carry out actions.
With an Event-driven architecture each service publishes an event whenever it updates or creates a data. Other services can subscribe to events. It enables an application to maintain data consistency across multiple services without using distributed transactions.

Let us take an example of order management. When the Order management app creates an Order in a pending state and publishes an Order Created event. The Customer Service receives the event and attempts to process an Order. It then publishes an Order Update event. Then Order Update Service receives the event from the changes the state of the order to either approved or canceled or fulfilled. The following diagram show the event driven architect

Terminology
Event
A change in state that is meaningful in a business process. For example, a placement of an order is a meaningful event because the order fulfillment center requires notification to process the order.
Event Notifier
A message that contains data about the event. Also known as an event notification.
Event producer
The publisher of an event message over a channel.
Channel
A conduit in which an event producer transmits a message. Event consumers subscribe to the channel to receive messages.
Event consumer
A subscriber to a channel that receives messages from the channel. A change in state that is meaningful in a business process.
But when you overlook at Platform events it makes similar to Streaming API and most of the futures including the replayID and durability but below makes the difference between with streaming API.
Publishing and subscribing Platform events
Publishing and subscribing the platform event are more flexible. You can publish event messages from a Force.com app or an external app using Apex or Salesforce APIs and you can subscribe from the Salesforce or external apps or use long polling with cometD as well.
Define Plat form Event
Define platform event similar like custom object, go to setup –> develope –> Platform events –> create new platform events as shown below.

Publish Platform events
1.a. Publish Using Apex
A trigger processes platform event notification sequentially in the order they’re received and trigger runs in its own process asynchronously and isn’t part of the transaction that published the event. Salesforce has a special class to publish the platform events EventBus which is having methods publish method. once the event is published you can consume the events from the channel
trigger PlatformEventPublish on Account (after insert , after update ) {
If(trigger.isAfter && trigger.isUpdate){
List<Employee_On_boarding__e> publishEvents = new List<Employee_On_boarding__e>();
for(Account a : Trigger.new){
Employee_On_boarding__e eve = new Employee_On_boarding__e();
eve.Name__c = a.Name ;
eve.Phone__c = a.Phone ;
eve.Salary__c = a.AnnualRevenue ;
publishEvents.add(eve);
}
if(publishEvents.size()>0){
EventBus.publish(publishEvents);
}
}
}1.b. Publish Using Process Builder

1.c. Publish Events by Flow
Create flow: 1(platform Event producer)


Create flow:2(Platform Event Consumer)


Run/Debug Flow:1(platform Event producer) and you will send post in chatter.

Result:

1.d. Publish Events by Using API (Using workbench)

Subscribe for Platform events
We can subscribe to the platform events from the Platform events object trigger which is created in step 1. Here is the sample trigger show how you can handle the subscribed events. create new accounts from the platform event but you can implement your own business logic to update the data.
Using Trigger:
trigger OnBoardingTrigger on Employee_On_boarding__e (after insert) {
List<Account> acc = new List<Account>();
for(Employee_On_boarding__e oBording :trigger.new){
acc.add(new Account(Name =oBording.Name__c , Phone =oBording.Phone__c , AnnualRevenue = oBording.Salary__c));
}
if(acc.size() >0){
insert acc ;
}
}Below is simple visual force page that consumes the platform events which you published. This page is built on cometD.
CometD is a set of library to write web applications that perform messaging over the web.Whenever you need to write applications where clients need to react to server-side events, then CometD is a very good choice. Think chat applications, online games, monitoring consoles, collaboration tools, stock trading, etc.
you can consume the platform events by using this URI /event/Employee_On_boarding__e and the Complete code is here below.
<apex:page standardStylesheets="false" showHeader="false" sidebar="false">
<div id="content">
</div>
<apex:includeScript value="{!$Resource.cometd}"/>
<apex:includeScript value="{!$Resource.jquery}"/>
<apex:includeScript value="{!$Resource.json2}"/>
<apex:includeScript value="{!$Resource.jquery_cometd}"/>
<script type="text/javascript">
(function($){
$(document).ready(function() {
$.cometd.configure({
url: window.location.protocol+'//'+window.location.hostname+ (null != window.location.port ? (':'+window.location.port) : '') +'/cometd/40.0/',
requestHeaders: { Authorization: 'OAuth {!$Api.Session_ID}'}
});
$.cometd.handshake();
$.cometd.addListener('/meta/handshake', function(message) {
$.cometd.subscribe('/event/Employee_On_boarding__e', function(message) {
var div = document.getElementById('content');
div.innerHTML = div.innerHTML + '<p>Notification </p><br/>' +
'Streaming Message ' + JSON.stringify(message) + '</p><br>';
});
})
});
})(jQuery)
</script>
</apex:page>