Lightning Web Components (LWC) Complete Tutorial for Beginners to Advanced
LWC (Lightning Web Components) is Salesforce's modern UI framework used to build fast, reusable, and responsive components using standard HTML, JavaScript, and CSS. It is built on modern web standards and provides better performance than Aura Components.
1. LWC Architecture
An LWC component consists of:
myComponent
│
├── myComponent.html
├── myComponent.js
├── myComponent.js-meta.xml
└── myComponent.css (optional)
HTML
Contains UI
JavaScript
Contains logic
CSS
Contains styling
XML
Controls component exposure
2. Create First LWC Program (Addition)
addition.html
<template>
<lightning-card title="Addition Program">
<div class="slds-p-around_medium">
<lightning-input
label="First Number"
type="number"
value={num1}
onchange={handleNum1}>
</lightning-input>
<lightning-input
label="Second Number"
type="number"
value={num2}
onchange={handleNum2}>
</lightning-input>
<lightning-button
label="Add"
variant="brand"
onclick={calculate}>
</lightning-button>
<h2 class="slds-m-top_medium">
Result : {result}
</h2>
</div>
</lightning-card>
</template>
addition.js
import { LightningElement } from 'lwc';
export default class Addition extends LightningElement {
num1 = 0;
num2 = 0;
result = 0;
handleNum1(event){
this.num1 = Number(event.target.value);
}
handleNum2(event){
this.num2 = Number(event.target.value);
}
calculate(){
this.result = this.num1 + this.num2;
}
}addition.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle
xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
</targets>
</LightningComponentBundle>3. Important Form Elements in LWC
1. Textbox
<lightning-input
label="Name"
type="text">
</lightning-input>
2. Number
<lightning-input
label="Age"
type="number">
</lightning-input>
3. Email
<lightning-input
label="Email"
type="email">
</lightning-input>
4. Password
<lightning-input
label="Password"
type="password">
</lightning-input>
5. Phone
<lightning-input
label="Phone"
type="tel">
</lightning-input>
6. Checkbox
<lightning-input
label="Accept Terms"
type="checkbox">
</lightning-input>
7. Radio Group
<lightning-radio-group
label="Gender"
options={genderOptions}
value={gender}>
</lightning-radio-group>genderOptions = [
{label:'Male',value:'Male'},
{label:'Female',value:'Female'}
];
8. Combobox (Dropdown)
<lightning-combobox
label="Country"
options={countryOptions}>
</lightning-combobox>countryOptions = [
{label:'India',value:'India'},
{label:'USA',value:'USA'}
];
9. Textarea
<lightning-textarea
label="Address">
</lightning-textarea>
10. Date Picker
<lightning-input
type="date"
label="Joining Date">
</lightning-input>
11. Date Time
<lightning-input
type="datetime">
</lightning-input>
12. File Upload
<lightning-file-upload
record-id={recordId}>
</lightning-file-upload>
13. Dual List Box
<lightning-dual-listbox
label="Skills"
options={skillOptions}>
</lightning-dual-listbox>
14. Slider
<lightning-slider
label="Experience"
value="5">
</lightning-slider>
Example :employeeRegistration.html
<template>
<lightning-card title="Employee Registration Form">
<div class="slds-p-around_medium">
<!-- Text -->
<lightning-input
label="Full Name"
type="text"
value={employee.name}
onchange={handleChange}>
</lightning-input>
<!-- Email -->
<lightning-input
label="Email"
type="email"
value={employee.email}
onchange={handleChange}>
</lightning-input>
<!-- Password -->
<lightning-input
label="Password"
type="password"
value={employee.password}
onchange={handleChange}>
</lightning-input>
<!-- Phone -->
<lightning-input
label="Phone"
type="tel"
value={employee.phone}
onchange={handleChange}>
</lightning-input>
<!-- Number -->
<lightning-input
label="Experience (Years)"
type="number"
value={employee.experience}
onchange={handleChange}>
</lightning-input>
<!-- Date -->
<lightning-input
label="Joining Date"
type="date"
value={employee.joiningDate}
onchange={handleChange}>
</lightning-input>
<!-- Date Time -->
<lightning-input
label="Interview Date Time"
type="datetime"
value={employee.interviewDate}
onchange={handleChange}>
</lightning-input>
<!-- Checkbox -->
<lightning-input
label="Accept Terms & Conditions"
type="checkbox"
checked={employee.acceptTerms}
onchange={handleCheckbox}>
</lightning-input>
<!-- Radio Group -->
<lightning-radio-group
label="Gender"
options={genderOptions}
value={employee.gender}
onchange={handleGender}>
</lightning-radio-group>
<!-- Combobox -->
<lightning-combobox
label="Department"
options={departmentOptions}
value={employee.department}
onchange={handleDepartment}>
</lightning-combobox>
<!-- Text Area -->
<lightning-textarea
label="Address"
value={employee.address}
onchange={handleAddress}>
</lightning-textarea>
<!-- Dual List Box -->
<lightning-dual-listbox
label="Skills"
source-label="Available Skills"
selected-label="Selected Skills"
options={skillOptions}
value={employee.skills}
onchange={handleSkills}>
</lightning-dual-listbox>
<!-- Slider -->
<lightning-slider
label="Communication Skill Rating"
min="0"
max="10"
value={employee.rating}
onchange={handleRating}>
</lightning-slider>
<!-- File Upload -->
<lightning-file-upload
label="Upload Resume"
record-id={recordId}
accepted-formats={acceptedFormats}
onuploadfinished={handleUploadFinished}>
</lightning-file-upload>
<br/>
<lightning-button
label="Submit"
variant="brand"
onclick={submitForm}>
</lightning-button>
</div>
</lightning-card>
</template>
employeeRegistration.js
import { LightningElement, track } from 'lwc';
export default class EmployeeRegistration extends LightningElement {
recordId = '001XXXXXXXXXXXXXXX';
acceptedFormats = ['.pdf','.doc','.docx'];
@track employee = {
name:'',
email:'',
password:'',
phone:'',
experience:'',
joiningDate:'',
interviewDate:'',
acceptTerms:false,
gender:'',
department:'',
address:'',
skills:[],
rating:5
};
genderOptions = [
{ label:'Male', value:'Male' },
{ label:'Female', value:'Female' },
{ label:'Other', value:'Other' }
];
departmentOptions = [
{ label:'Development', value:'Development' },
{ label:'Testing', value:'Testing' },
{ label:'Salesforce', value:'Salesforce' },
{ label:'DevOps', value:'DevOps' }
];
skillOptions = [
{ label:'Java', value:'Java' },
{ label:'Python', value:'Python' },
{ label:'C#', value:'C#' },
{ label:'Salesforce', value:'Salesforce' },
{ label:'React', value:'React' }
];
handleChange(event){
const label = event.target.label;
if(label === 'Full Name')
this.employee.name = event.target.value;
else if(label === 'Email')
this.employee.email = event.target.value;
else if(label === 'Password')
this.employee.password = event.target.value;
else if(label === 'Phone')
this.employee.phone = event.target.value;
else if(label === 'Experience (Years)')
this.employee.experience = event.target.value;
else if(label === 'Joining Date')
this.employee.joiningDate = event.target.value;
else if(label === 'Interview Date Time')
this.employee.interviewDate = event.target.value;
}
handleCheckbox(event){
this.employee.acceptTerms = event.target.checked;
}
handleGender(event){
this.employee.gender = event.detail.value;
}
handleDepartment(event){
this.employee.department = event.detail.value;
}
handleAddress(event){
this.employee.address = event.target.value;
}
handleSkills(event){
this.employee.skills = event.detail.value;
}
handleRating(event){
this.employee.rating = event.detail.value;
}
handleUploadFinished(event){
const uploadedFiles = event.detail.files;
alert(uploadedFiles.length + ' File Uploaded');
}
submitForm(){
console.log(
JSON.stringify(this.employee)
);
alert(
'Employee Registered Successfully'
);
}
}What is @wire?
Wire Service is a reactive service used to fetch Salesforce data automatically.
When underlying data changes, component automatically updates.
Characteristics
✅ Automatic execution
✅ Reactive
✅ Cached
✅ Read Operations
❌ Not suitable for DML
Wire Example
Apex Class
public with sharing class AccountController {
@AuraEnabled(cacheable=true)
public static List<Account> getAccounts(){
return [
SELECT Id,Name
FROM Account
LIMIT 10
];
}
}
JS
import { LightningElement, wire }
from 'lwc';
import getAccounts
from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
accounts;
@wire(getAccounts)
wiredAccounts({data,error}){
if(data){
this.accounts = data;
}
if(error){
console.error(error);
}
}
}
HTML
<template>
<template for:each={accounts}
for:item="acc">
<p key={acc.Id}>
{acc.Name}
</p>
</template>
</template>
What is Imperative Apex Call?
Imperative means you manually call Apex method.
Used for:
✔ Create
✔ Update
✔ Delete
✔ Button Click
✔ On Demand Calls
Apex
@AuraEnabled
public static String saveData(){
return 'Saved';
}
JS
import saveData
from '@salesforce/apex/MyController.saveData';
saveRecord(){
saveData()
.then(result=>{
console.log(result);
})
.catch(error=>{
console.error(error);
});
}Wire vs Imperative
Feature Wire Imperative Auto Call Yes No Reactive Yes No Cacheable Yes Optional DML Support No Yes User Action No Yes Read Data Best Good Save Data No Best LWC Decorators (Annotations)
LWC provides three important decorators: @api, @track, @wire.
They add special functionality to properties and methods.
A. @api
Used to expose public property or method.
Parent → Child Communication.
Child Component
import { LightningElement, api }
from 'lwc';
export default class ChildComponent
extends LightningElement {
@api message;
}
Child HTML
<template>
{message}
</template>
Parent HTML
<c-child-component
message="Welcome Shiva Sir">
</c-child-component>
@api Method Example
Child JS
import { LightningElement, api }
from 'lwc';
export default class ChildComponent
extends LightningElement {
@api showAlert(){
alert('Hello');
}
}
Parent JS
callChild(){
this.template
.querySelector('c-child-component')
.showAlert();
}
B. @track
Used for object and array reactivity. When tracked properties change, UI updates automatically.
import { LightningElement, track }
from 'lwc';
export default class TrackExample
extends LightningElement {
@track employee = {
name:'Shiva',
city:'Indore'
};
updateName(){
this.employee.name =
'Rahul';
}
}
HTML
<template>
<h1>
{employee.name}
</h1>
<lightning-button
label="Update"
onclick={updateName}>
</lightning-button>
</template>
C. @wire
Used to fetch Salesforce data reactively.
@wire(getAccounts)
accounts;or
@wire(getAccounts)
wiredAccounts({data,error}){
}Lifecycle Hooks in LWC
constructor()
constructor(){
super();
}Runs first.
connectedCallback()
connectedCallback(){
console.log('Component Loaded');
}Runs when component inserted into DOM.
renderedCallback()
renderedCallback(){
console.log('Rendered');
}Runs after rendering.
disconnectedCallback()
disconnectedCallback(){
console.log('Removed');
}Runs when removed.
errorCallback()
errorCallback(error,stack){
}Handles child component errors.
0 Comments
POST Answer of Questions and ASK to Doubt