Ad Code

✨🎆 JOIN MERN, JAVA, PYTHON, AI, DEVOPS, SALESFORCE Courses 🎆✨

Get 100% Placement Oriented Program CLICK to new more info click

LWC in depth tutorial:

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
];
}
}

FOR INSERT AND SELECT BOTH

public with sharing class AccountController { // Get Accounts @AuraEnabled(cacheable=true) public static List<Account> getAccounts(){ return [ SELECT Id, Name FROM Account ORDER BY CreatedDate DESC LIMIT 10 ]; } // Insert Account @AuraEnabled public static Account createAccount(String accountName){ Account acc = new Account(); acc.Name = accountName; insert acc; return acc; } }

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);
}
}
}

.JS FILE
import { LightningElement, wire } from 'lwc'; import getAccounts from '@salesforce/apex/AccountController.getAccounts'; import createAccount from '@salesforce/apex/AccountController.createAccount'; import { refreshApex } from '@salesforce/apex'; export default class AccountList extends LightningElement { accounts; accountName; wiredResult; @wire(getAccounts) wiredAccounts(result){ this.wiredResult = result; if(result.data){ this.accounts = result.data; } if(result.error){ console.error(result.error); } } handleChange(event){ this.accountName = event.target.value; } saveAccount(){ createAccount({ accountName : this.accountName }) .then(result=>{ console.log( 'Account Created', result.Id ); this.accountName = ''; // Refresh list return refreshApex(this.wiredResult); }) .catch(error=>{ console.error(error); }) } }

HTML

<template>

<template for:each={accounts}
for:item="acc">

<p key={acc.Id}>
{acc.Name}
</p>

</template>

</template>

for insert also
<template> <lightning-card title="Account Creation"> <div class="slds-p-around_medium"> <lightning-input label="Account Name" value={accountName} onchange={handleChange}> </lightning-input> <lightning-button label="Save Account" onclick={saveAccount} class="slds-m-top_medium"> </lightning-button> </div> </lightning-card> <lightning-card title="Account List"> <template for:each={accounts} for:item="acc"> <p key={acc.Id}> {acc.Name} </p> </template> </lightning-card> </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

FeatureWireImperative
Auto CallYesNo
ReactiveYesNo
CacheableYesOptional
DML SupportNoYes
User ActionNoYes
Read DataBestGood
Save DataNoBest

LWC Decorators (Annotations)

LWC provides three important decorators: @api, @track, @wire.

They add special functionality to properties and methods.



public with sharing class AccountController { // READ @AuraEnabled public static List<Account> getAccounts(){ return [ SELECT Id, Name, Phone, Industry FROM Account ORDER BY CreatedDate DESC LIMIT 50 ]; } // CREATE @AuraEnabled public static Account createAccount( String name, String phone, String industry ){ Account acc = new Account(); acc.Name = name; acc.Phone = phone; acc.Industry = industry; insert acc; return acc; } // UPDATE @AuraEnabled public static Account updateAccount( Id accountId, String name, String phone, String industry ){ Account acc = new Account(); acc.Id = accountId; acc.Name = name; acc.Phone = phone; acc.Industry = industry; update acc; return acc; } // DELETE @AuraEnabled public static void deleteAccount(Id accountId){ Account acc = new Account( Id = accountId ); delete acc; } }

<template> <lightning-card title="Account CRUD Using Imperative Call"> <div class="slds-p-around_medium"> <!-- CREATE / UPDATE FORM --> <lightning-input label="Account Name" value={accountName} onchange={handleName}> </lightning-input> <lightning-input label="Phone" value={phone} onchange={handlePhone}> </lightning-input> <lightning-input label="Industry" value={industry} onchange={handleIndustry}> </lightning-input> <br> <lightning-button label={buttonLabel} variant="brand" onclick={saveAccount}> </lightning-button> <lightning-button label="Clear" onclick={clearForm} class="slds-m-left_small"> </lightning-button> <hr> <h2>Account List</h2> <template if:true={accounts}> <template for:each={accounts} for:item="acc"> <div key={acc.Id} class="slds-box slds-m-around_small"> <b>{acc.Name}</b> <p> Phone : {acc.Phone} </p> <p> Industry : {acc.Industry} </p> <lightning-button label="Edit" data-id={acc.Id} onclick={editAccount}> </lightning-button> <lightning-button label="Delete" variant="destructive" data-id={acc.Id} onclick={deleteAccount} class="slds-m-left_small"> </lightning-button> </div> </template> </template> </div> </lightning-card> </template>


import { LightningElement } from 'lwc'; import getAccounts from '@salesforce/apex/AccountController.getAccounts'; import createAccount from '@salesforce/apex/AccountController.createAccount'; import updateAccount from '@salesforce/apex/AccountController.updateAccount'; import deleteAccount from '@salesforce/apex/AccountController.deleteAccount'; import {ShowToastEvent} from 'lightning/platformShowToastEvent'; export default class AccountCrud extends LightningElement { accounts=[]; accountId; accountName=''; phone=''; industry=''; buttonLabel='Save'; connectedCallback(){ this.loadAccounts(); } // READ loadAccounts(){ getAccounts() .then(result=>{ this.accounts=result; }) .catch(error=>{ this.showToast( 'Error', error.body.message, 'error' ); }) } handleName(event){ this.accountName = event.target.value; } handlePhone(event){ this.phone = event.target.value; } handleIndustry(event){ this.industry = event.target.value; } // CREATE + UPDATE saveAccount(){ if(this.accountId){ // UPDATE updateAccount({ accountId:this.accountId, name:this.accountName, phone:this.phone, industry:this.industry }) .then(()=>{ this.showToast( 'Success', 'Account Updated', 'success' ); this.clearForm(); this.loadAccounts(); }) .catch(error=>{ this.showToast( 'Error', error.body.message, 'error' ); }) } else{ // CREATE createAccount({ name:this.accountName, phone:this.phone, industry:this.industry }) .then(()=>{ this.showToast( 'Success', 'Account Created', 'success' ); this.clearForm(); this.loadAccounts(); }) .catch(error=>{ this.showToast( 'Error', error.body.message, 'error' ); }) } } // EDIT editAccount(event){ let id = event.target.dataset.id; let selected = this.accounts.find( item=>item.Id==id ); this.accountId = selected.Id; this.accountName = selected.Name; this.phone = selected.Phone; this.industry = selected.Industry; this.buttonLabel="Update"; } // DELETE deleteAccount(event){ let id = event.target.dataset.id; deleteAccount({ accountId:id }) .then(()=>{ this.showToast( 'Deleted', 'Account Deleted', 'success' ); this.loadAccounts(); }) .catch(error=>{ this.showToast( 'Error', error.body.message, 'error' ); }) } clearForm(){ this.accountId=null; this.accountName=''; this.phone=''; this.industry=''; this.buttonLabel="Save"; } showToast(title,message,variant){ this.dispatchEvent( new ShowToastEvent({ title:title, message:message, variant:variant }) ); } }

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.


Below is a complete Lightning Data Service (LDS) example in LWC without using Apex.

This example displays an Account record and allows the user to update its Name and Phone.


Project Structure

force-app
 └── main
     └── default
         └── lwc
             └── accountEditor
                 ├── accountEditor.html
                 ├── accountEditor.js
                 ├── accountEditor.js-meta.xml

Step 1: accountEditor.html

<template>

    <lightning-card title="Account Details using LDS">

        <template if:true={account.data}>

            <div class="slds-p-around_medium">

                <p>
                    <strong>Name :</strong>
                    {account.data.fields.Name.value}
                </p>

                <p>
                    <strong>Phone :</strong>
                    {account.data.fields.Phone.value}
                </p>

            </div>

        </template>

        <div class="slds-p-around_medium">

            <lightning-input
                label="New Account Name"
                value={name}
                onchange={handleName}>
            </lightning-input>

            <lightning-input
                label="Phone"
                value={phone}
                onchange={handlePhone}>
            </lightning-input>

            <br/>

            <lightning-button
                label="Update Account"
                variant="brand"
                onclick={updateAccount}>
            </lightning-button>

        </div>

    </lightning-card>

</template>

Step 2: accountEditor.js

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

import { getRecord } from 'lightning/uiRecordApi';

import { updateRecord } from 'lightning/uiRecordApi';

import { ShowToastEvent } from 'lightning/platformShowToastEvent';

const FIELDS = [
    'Account.Name',
    'Account.Phone'
];

export default class AccountEditor extends LightningElement {

    @api recordId;

    name;
    phone;

    @wire(getRecord, {
        recordId: '$recordId',
        fields: FIELDS
    })
    account;

    handleName(event) {
        this.name = event.target.value;
    }

    handlePhone(event) {
        this.phone = event.target.value;
    }

    updateAccount() {

        const fields = {};

        fields.Id = this.recordId;
        fields.Name = this.name;
        fields.Phone = this.phone;

        const recordInput = {
            fields: fields
        };

        updateRecord(recordInput)
            .then(() => {

                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Account Updated Successfully',
                        variant: 'success'
                    })
                );

            })
            .catch(error => {

                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error',
                        message: error.body.message,
                        variant: 'error'
                    })
                );

            });

    }

}

Step 3: accountEditor.js-meta.xml

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

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

    <apiVersion>64.0</apiVersion>

    <isExposed>true</isExposed>

    <targets>

        <target>lightning__RecordPage</target>

        <target>lightning__AppPage</target>

        <target>lightning__HomePage</target>

    </targets>

</LightningComponentBundle>

How it Works

Step 1

When the Account Record Page opens,

@wire(getRecord,{
    recordId:'$recordId',
    fields:FIELDS
})

fetches the Account automatically.

Example Data:

Id      : 001XXXXXXXXXXXX
Name    : ABC Pvt Ltd
Phone   : 9876543210

Step 2

The user enters:

Name  : TechForest Pvt Ltd
Phone : 9999999999

Step 3

Click Update Account

This executes

updateRecord(recordInput)

which updates Salesforce without Apex.


Other LDS Methods

Read Record

import { getRecord } from 'lightning/uiRecordApi';

Create Record

import { createRecord } from 'lightning/uiRecordApi';

const fields = {};

fields.Name = 'Shiva Concept Solution';

const recordInput = {
    apiName: 'Account',
    fields: fields
};

createRecord(recordInput)
.then(result=>{
    console.log(result.id);
});

Delete Record

import { deleteRecord } from 'lightning/uiRecordApi';

deleteRecord(recordId)
.then(()=>{
    console.log("Deleted");
});

Using Base Components (No JavaScript Needed)

View Record

<lightning-record-view-form
    record-id={recordId}
    object-api-name="Account">

    <lightning-output-field field-name="Name"></lightning-output-field>

    <lightning-output-field field-name="Phone"></lightning-output-field>

</lightning-record-view-form>

Edit Record

<lightning-record-edit-form
    object-api-name="Account"
    record-id={recordId}>

    <lightning-input-field field-name="Name"></lightning-input-field>

    <lightning-input-field field-name="Phone"></lightning-input-field>

    <lightning-button
        type="submit"
        label="Save">
    </lightning-button>

</lightning-record-edit-form>

Below is a real-world complete CRUD application using Lightning Data Service (LDS) without Apex.

This project covers:

  • ✅ Create Account
  • ✅ Read Accounts
  • ✅ Update Account
  • ✅ Delete Account
  • ✅ Toast Messages
  • ✅ Refresh Data
  • ✅ Lightning Design System
  • ✅ No Apex
  • ✅ Interview Ready

Project Structure

lwc
|
|-- accountCrud
      |
      |-- accountCrud.html
      |-- accountCrud.js
      |-- accountCrud.js-meta.xml

Step 1 Create LWC

sfdx force:lightning:component:create \
--type lwc \
--componentname accountCrud

Step 2 HTML

accountCrud.html

<template>
<lightning-card title="Lightning Data Service CRUD Example">
<div class="slds-p-around_medium">
<lightning-input
label="Account Name"
value={name}
onchange={handleName}>
</lightning-input>
<lightning-input
label="Phone"
value={phone}
onchange={handlePhone}>
</lightning-input>
<lightning-button
label="Save"
variant="brand"
onclick={saveRecord}
class="slds-m-top_medium">
</lightning-button>
</div>
<template if:true={accounts}>
<table class="slds-table slds-table_cell-buffer slds-table_bordered">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<template for:each={accounts} for:item="acc">
<tr key={acc.Id}>
<td>{acc.Name}</td>
<td>{acc.Phone}</td>
<td>
<lightning-button
label="Edit"
data-id={acc.Id}
onclick={editRecord}>
</lightning-button>
</td>
<td>
<lightning-button
variant="destructive"
label="Delete"
data-id={acc.Id}
onclick={deleteAccount}>
</lightning-button>
</td>
</tr>
</template>
</tbody>
</table>
</template>
</lightning-card> </template>


Step 3 JavaScript

accountCrud.js

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

import { ShowToastEvent } from 'lightning/platformShowToastEvent';

import ACCOUNT_OBJECT from '@salesforce/schema/Account';

import NAME_FIELD from '@salesforce/schema/Account.Name';

import PHONE_FIELD from '@salesforce/schema/Account.Phone';

import ID_FIELD from '@salesforce/schema/Account.Id';

import { createRecord, updateRecord, deleteRecord } from 'lightning/uiRecordApi';

import { getListUi } from 'lightning/uiListApi';

export default class AccountCrud extends LightningElement {

    @track accounts=[];

    name='';

    phone='';

    recordId='';

    @wire(getListUi,{
        objectApiName:ACCOUNT_OBJECT,
        listViewApiName:'AllAccounts'
    })

    wiredList({data,error}){

        if(data){

            this.accounts=data.records.records.map(record=>{

                return{

                    Id:record.id,

                    Name:record.fields.Name.value,

                    Phone:record.fields.Phone
                    ?record.fields.Phone.value
                    :''
                };

            });

        }

    }

    handleName(event){

        this.name=event.target.value;

    }

    handlePhone(event){

        this.phone=event.target.value;

    }

    saveRecord(){

        if(this.recordId){

            this.updateAccount();

        }

        else{

            this.createAccount();

        }

    }

    createAccount(){

        const fields={};

        fields[NAME_FIELD.fieldApiName]=this.name;

        fields[PHONE_FIELD.fieldApiName]=this.phone;

        const recordInput={

            apiName:ACCOUNT_OBJECT.objectApiName,

            fields

        };

        createRecord(recordInput)

        .then(()=>{

            this.showToast("Success","Account Created","success");

            this.clearForm();

        })

        .catch(error=>{

            this.showToast("Error",error.body.message,"error");

        });

    }

    editRecord(event){

        let id=event.target.dataset.id;

        let acc=this.accounts.find(x=>x.Id===id);

        this.recordId=id;

        this.name=acc.Name;

        this.phone=acc.Phone;

    }

    updateAccount(){

        const fields={};

        fields[ID_FIELD.fieldApiName]=this.recordId;

        fields[NAME_FIELD.fieldApiName]=this.name;

        fields[PHONE_FIELD.fieldApiName]=this.phone;

        updateRecord({fields})

        .then(()=>{

            this.showToast("Updated","Record Updated","success");

            this.clearForm();

        })

        .catch(error=>{

            this.showToast("Error",error.body.message,"error");

        });

    }

    deleteAccount(event){

        deleteRecord(event.target.dataset.id)

        .then(()=>{

            this.showToast("Deleted","Record Deleted","success");

        })

        .catch(error=>{

            this.showToast("Error",error.body.message,"error");

        });

    }

    clearForm(){

        this.name='';

        this.phone='';

        this.recordId='';

    }

    showToast(title,message,variant){

        this.dispatchEvent(

            new ShowToastEvent({

                title,

                message,

                variant

            })

        );

    }

}

Step 4 Meta XML

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

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

    <apiVersion>62.0</apiVersion>

    <isExposed>true</isExposed>

    <targets>

        <target>lightning__AppPage</target>

        <target>lightning__RecordPage</target>

        <target>lightning__HomePage</target>

    </targets>

</LightningComponentBundle>

Flow Diagram

            User

              │

              ▼

        Enter Account

              │

              ▼

       Click Save Button

              │

              ▼

      createRecord()

              │

              ▼

       Salesforce Database

              │

              ▼

        LDS Cache Updated

              │

              ▼

      UI Automatically Refreshes

Update Flow

Click Edit

↓

Fill Textboxes

↓

Click Save

↓

updateRecord()

↓

Database

↓

LDS Cache

↓

UI Refresh

Delete Flow

Click Delete

↓

deleteRecord()

↓

Database

↓

LDS Cache

↓

Record Removed

Interview Questions

Q1. Difference between Aura and LWC?

  • Aura uses proprietary framework.
  • LWC uses modern JavaScript standards.
  • LWC is faster.

Q2. Difference between @wire and Imperative?

  • Wire → Automatic
  • Imperative → Manual

Q3. When use @api?

  • Parent to Child communication.

Q4. When use @track?

  • Object and Array reactivity.

Q5. Can @wire perform DML?

  • No. Use Imperative Apex.

Q6. Which decorator fetches Salesforce data?

  • @wire.

This covers the foundation of LWC development: component structure, form controls,

wire service, imperative Apex, decorators, lifecycle hooks, and practical examples.

It is enough to start building real Salesforce applications and prepare for Salesforce Developer

interviews.


Post a Comment

0 Comments