Introduction to Lightning Web Components (LWC)
Lightning Web Components (LWC) is a modern JavaScript framework for building reusable and high-performance web components on the Salesforce platform. It leverages web standards and delivers a lightweight framework with a consistent developer experience. This blog will walk you through the essential features, advantages, and practical examples to help you get started with LWC.Features & Advantages
LWC stands out due to several key features:- Web Standards: LWC leverages W3C web standards.
- Modern JavaScript: Uses ES6 standards.
- Simplified Data Access: Utilizes decorators like
@wire
. - Shadow DOM: Ensures encapsulation and high performance.
- API Versioning: Supports multiple API versions.
- Open Source: LWC is open-source.
Getting Started
To create and deploy an LWC app, follow these steps:Step 1: Create Salesforce DX Project
In Visual Studio Code, pressCommand + Shift + P
, type sfdx
, and select SFDX: Create Project
. Name your project MyLWC
.
Step 2: Authorize an Org
In VS Code, pressCommand + Shift + P
, type sfdx
, and select SFDX: Authorize an Org
. Follow the prompts to log in.
Step 3: Create a Lightning Web Component
In VS Code, pressCommand + Shift + P
, type sfdx
, and select SFDX: Create Lightning Web Component
. Name your component myHelloWorld
.
Step 4: Deploy to Org
Right-click thedefault
folder under force-app/main
, and select SFDX: Deploy Source to Org
.
Step 5: Add Component to App
Open the page where you want to add the component, dragmyHelloWorld
onto the page, and save.
Component Bundles & Rules
A component folder typically contains:- HTML File: Defines the component’s template.
- JavaScript File: Contains the component’s logic.
- XML File: Configuration file for metadata.
myComponent
├── myComponent.html
├── myComponent.js
├── myComponent.js-meta.xml
├── myComponent.css
└── __tests__
└── myComponent.test.js
Reactivity
LWC components automatically react to changes in properties:Reactive Properties
- Primitive Fields: Booleans, numbers, and strings are reactive.
- Decorators:
@api
: Exposes a public property.@track
: Observes changes in object properties or array elements.@wire
: Binds data from Salesforce.
<!-- myComponent.html -->
<template>
<div class="view">
<label>{title}</label>
</div>
<p>{fullName}</p>
<lightning-button label="Change Name" onclick={handleClick}></lightning-button>
</template>
// myComponent.js
import { LightningElement, track, api } from 'lwc';
export default class MyComponent extends LightningElement {
@api title = 'Sample Example';
@track fullName = { firstName: '', lastName: '' };
handleClick() {
this.fullName.firstName = 'John';
}
}
Composition
Communicate between parent and child components using properties and methods:Parent to Child Data Flow
Use@api
to set properties on child components.
Example:
<!-- todoApp.html -->
<template>
<c-todo-wrapper>
<c-todo-item item-name={itemName}></c-todo-item>
</c-todo-wrapper>
<p>Item in todoApp: {itemName}</p>
<p><button onclick={updateItemName}>Update Item Name</button></p>
</template>
// todoApp.js
import { LightningElement, track } from 'lwc';
export default class TodoApp extends LightningElement {
@track itemName = 'Milk';
updateItemName() {
this.itemName = 'Updated Item Name in todoApp';
}
}
Working with DOM
Understand the differences between Shadow DOM and Light DOM:Shadow DOM
Encapsulates component elements, providing style and behavior isolation. Example:
<!-- c-todo-app -->
<template>
<p>Your To-Do List</p>
<c-todo-item></c-todo-item>
</template>
Light DOM
Avoids Shadow DOM limitations, making third-party integrations easier. Example:
import { LightningElement } from 'lwc';
export default class LightDomApp extends LightningElement {
static renderMode = 'light';
}
<template lwc:render-mode="light"></template>
Communicate with Events
Creating and Dispatching Events
Example:
// c-child.js
import { LightningElement, api } from 'lwc';
export default class Child extends LightningElement {
@api handleNotification;
handleClick() {
const event = new CustomEvent('notification', {
detail: { message: 'Hello from Child' }
});
this.dispatchEvent(event);
}
}
<!-- parentComponent.html -->
<template>
<c-child onnotification={handleNotification}></c-child>
</template>
// parentComponent.js
import { LightningElement } from 'lwc';
export default class ParentComponent extends LightningElement {
handleNotification(event) {
console.log(event.detail.message);
}
}
Working with Salesforce Data
Using Lightning Data Service (LDS)
LDS provides data access and caching for Salesforce records. Example:
import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import ACCOUNT_NAME_FIELD from '@salesforce/schema/Account.Name';
export default class MyComponent extends LightningElement {
@api recordId;
@wire(getRecord, { recordId: '$recordId', fields: [ACCOUNT_NAME_FIELD] })
record;
}
Calling Apex Methods
Example:
import { LightningElement, wire } from 'lwc';
import getContacts from '@salesforce/apex/ContactController.getContactList';
export default class ContactList extends LightningElement {
@wire(getContacts)
contacts;
}
Aura-Component Co-existence
LWC can interoperate with Aura components, allowing gradual migration to LWC.LWC Best Practices
- Use Decorators:
@api
,@track
, and@wire
. - Shadow DOM: Leverage Shadow DOM for encapsulation.
- Efficient Data Access: Use LDS and wire services for optimized data handling.
- Component Reusability: Create modular and reusable components.
- Event Handling: Use custom events for communication between components.