Converting Lightning component to LWC
Today we will see how can we convert an existing Lightning Component to Lightning Web Component (LWC). I will convert the Org Limits Lightning component that I published in my last blog spot to a LWC component.
The basic structure of a lightning web component consists of a HTML file, a JS file and a xml file.
The basic structure of a lightning web component consists of a HTML file, a JS file and a xml file.
- The .html file in LWC is equivalent to the .cmp file present in Aura.
- The .js file in LWC is equivalent to the combination of controller.js and helper.js files present in Aura
- The xml file in LWC contains the meta information such as api version.
Lets see step by step how to convert the Org Limits component. First we will convert the OrgLimits.cmp to orgLimitsLWC.html
List of all component present in LWC
Below is the complete code for orgLimitsLWC.html
orgLimitsLWC.html
This file contains the API version and the interfaces required to expose this component in either App page, record page or home page.
The apex controller OrgLimitsCtrl remains unchanged.
<aura:component implements="flexipage:availableForAllPageTypes" controller="OrgLimitsCtrl">
The <aura:component> tag in LC gets replaced by <template> tag in LWC. The implements attribute containing value flexipage:availableForAllPageTypes gets shifted to the xml file present in LWC. The controller attribute containing value OrgLimitsCtrl is handled in the .js file present in LWC.
<!-- Attributes -->
<aura:attribute name="orgLimitInfo" type="List"/>
<aura:attribute name="lastRefreshedDate" type="DateTime" />
<aura:attribute name="timeZone" type="String" />
The aura:attribute tags gets shifted to the .js file present in LWC
<aura:attribute name="orgLimitInfo" type="List"/>
<aura:attribute name="lastRefreshedDate" type="DateTime" />
<aura:attribute name="timeZone" type="String" />
<!-- Event Handlers -->
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
The init event handler gets shifted to the .js file present in LWC. connectedCallback() in LWC is equivalent to init in LC.<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:iteration items="{!v.orgLimitInfo}" var="item">
The equivalent of aura:iteration in LWC is template for:each as shown below:
<template for:each={orgLimitInfo} for:item="item">
Other tags such as lightning:card present in LC gets converted to lightning-card in LWC. lightning:formattedDateTime present in LC gets converted to ightning-formatted-date-time in LWC. Almost all the components present in LC have an equivalent component present in LWC. You can access the complete list of LWC OOTB component using below link:List of all component present in LWC
Below is the complete code for orgLimitsLWC.html
orgLimitsLWC.html
<template>
<lightning-card title="Org Limits" icon-name="standard:work_capacity_limit">
<div slot="actions">
<div>As of </div>
<lightning-formatted-date-time value={lastRefreshedDate}
month="numeric"
day="numeric" hour="2-digit"
minute="2-digit"
hour12="true"></lightning-formatted-date-time>
<button name="Refresh" class="slds-button">
<span data-value="Refresh" onclick={connectedCallback}>
<lightning-icon icon-name="action:refresh" size="xx-small"></lightning-icon>
</span>
</button>
</div>
<template if:true={orgLimitInfo}>
<table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
<thead>
<tr class="slds-line-height_reset">
<th class="" scope="col">
<div class="slds-truncate" title="Limit Name">Limit Name</div>
</th>
<th class="" scope="col">
<div class="slds-truncate" title="Used">Used</div>
</th>
<th class="" scope="col">
<div class="slds-truncate" title="Available">Available</div>
</th>
</tr>
</thead>
<tbody>
<template for:each={orgLimitInfo} for:item="item">
<tr class="slds-hint-parent" key={item.limitName}>
<td data-label="Limit Name">
<div class="slds-truncate" title={item.limitName}>
{item.limitName}
</div>
</td>
<td data-label="Limit Name">
<div class="slds-truncate" title={item.usedLimit}>
{item.usedLimit}
</div>
</td>
<td data-label="Limit Name">
<div class="slds-truncate" title={item.maxLimit}>
{item.maxLimit}
</div>
</td>
</tr>
</template>
</tbody>
</table>
</template>
<template if:true={error}>
{error}
</template>
</lightning-card>
</template>
Now let's have a look at the JS controller - orgLimitsLWC.js<lightning-card title="Org Limits" icon-name="standard:work_capacity_limit">
<div slot="actions">
<div>As of </div>
<lightning-formatted-date-time value={lastRefreshedDate}
month="numeric"
day="numeric" hour="2-digit"
minute="2-digit"
hour12="true"></lightning-formatted-date-time>
<button name="Refresh" class="slds-button">
<span data-value="Refresh" onclick={connectedCallback}>
<lightning-icon icon-name="action:refresh" size="xx-small"></lightning-icon>
</span>
</button>
</div>
<template if:true={orgLimitInfo}>
<table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
<thead>
<tr class="slds-line-height_reset">
<th class="" scope="col">
<div class="slds-truncate" title="Limit Name">Limit Name</div>
</th>
<th class="" scope="col">
<div class="slds-truncate" title="Used">Used</div>
</th>
<th class="" scope="col">
<div class="slds-truncate" title="Available">Available</div>
</th>
</tr>
</thead>
<tbody>
<template for:each={orgLimitInfo} for:item="item">
<tr class="slds-hint-parent" key={item.limitName}>
<td data-label="Limit Name">
<div class="slds-truncate" title={item.limitName}>
{item.limitName}
</div>
</td>
<td data-label="Limit Name">
<div class="slds-truncate" title={item.usedLimit}>
{item.usedLimit}
</div>
</td>
<td data-label="Limit Name">
<div class="slds-truncate" title={item.maxLimit}>
{item.maxLimit}
</div>
</td>
</tr>
</template>
</tbody>
</table>
</template>
<template if:true={error}>
{error}
</template>
</lightning-card>
</template>
import {LightningElement, track} from 'lwc';
import getOrgLimits from '@salesforce/apex/OrgLimitsCtrl.getOrgLimits';
export default class OrgLimitsLWC extends LightningElement {
@track orgLimitInfo;
@track error;
@track lastRefreshedDate;
connectedCallback() {
getOrgLimits()
.then(result => {
this.lastRefreshedDate = new Date();
this.orgLimitInfo = result;
})
.catch(error => {
this.error = error;
});
}
}
import getOrgLimits from '@salesforce/apex/OrgLimitsCtrl.getOrgLimits';
export default class OrgLimitsLWC extends LightningElement {
@track orgLimitInfo;
@track error;
@track lastRefreshedDate;
connectedCallback() {
getOrgLimits()
.then(result => {
this.lastRefreshedDate = new Date();
this.orgLimitInfo = result;
})
.catch(error => {
this.error = error;
});
}
}
- Associating Apex controller: In Lightning component, we specify the name of apex class in the controller attribute of aura:component tag (the top-most tag on any lightning component). In LWC, we use an import statement to import the specific method from an apex controller. See example below:
import getOrgLimits from '@salesforce/apex/OrgLimitsCtrl.getOrgLimits';
- The two way binding of attributes is done via @track decorator. To track a private property’s value and rerender a component when it changes, decorate the property with @track. Tracked properties are also called private reactive properties.
- connectedCallback is the equivalent of init event handler present in Lightning component. 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.
The last file we need to understand is the orgLimitsLWC.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="orgLimitsLWC">
<apiVersion>46.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
The apex controller OrgLimitsCtrl remains unchanged.
public class OrgLimitsCtrl {
@AuraEnabled
public static List<OrgLimitInfo> getOrgLimits(){
Map<String,System.OrgLimit> limitsMap = OrgLimits.getMap();
List<OrgLimitInfo> orgLimitInfoList = new List<OrgLimitInfo>();
for(String limitName:limitsMap.keySet()) {
System.OrgLimit orgLimit = limitsMap.get(limitName);
orgLimitInfoList.add(new OrgLimitInfo(limitName, orgLimit.getValue(), orgLimit.getLimit()));
}
return orgLimitInfoList;
}
public class OrgLimitInfo{
@AuraEnabled
public String limitName {get;set;}
@AuraEnabled
public Integer usedLimit {get;set;}
@AuraEnabled
public Integer maxLimit {get;set;}
public OrgLimitInfo(String limitName, Integer usedLimit, Integer maxLimit){
this.limitName = limitName;
this.usedLimit = usedLimit;
this.maxLimit = maxLimit;
}
}
}
If you have any questions, feel free to post a comment and I will get back to you asap. Happy coding :)@AuraEnabled
public static List<OrgLimitInfo> getOrgLimits(){
Map<String,System.OrgLimit> limitsMap = OrgLimits.getMap();
List<OrgLimitInfo> orgLimitInfoList = new List<OrgLimitInfo>();
for(String limitName:limitsMap.keySet()) {
System.OrgLimit orgLimit = limitsMap.get(limitName);
orgLimitInfoList.add(new OrgLimitInfo(limitName, orgLimit.getValue(), orgLimit.getLimit()));
}
return orgLimitInfoList;
}
public class OrgLimitInfo{
@AuraEnabled
public String limitName {get;set;}
@AuraEnabled
public Integer usedLimit {get;set;}
@AuraEnabled
public Integer maxLimit {get;set;}
public OrgLimitInfo(String limitName, Integer usedLimit, Integer maxLimit){
this.limitName = limitName;
this.usedLimit = usedLimit;
this.maxLimit = maxLimit;
}
}
}
Comments
Post a Comment