This post continues from the previous one, which covered 20 LWC interview questions.
If you haven’t reviewed that post yet, I recommend checking it out to explore all 20 questions from LWC Interview Questions for Developers – Part 1.
21. What is the Lightning Locker Service, and how does it impact LWC?
The Lightning Locker Service is a security framework provided by Salesforce for Lightning Web Components (LWC) and Aura Components.
It enforces strict encapsulation and security boundaries to ensure that components are isolated from each other and cannot interfere with or access data they shouldn’t.
Think of it as a “security guard” that prevents components from stepping on each other’s toes.
Key Features of Lightning Locker Service
Component Isolation:
Each component runs in its own namespace, preventing it from accessing or modifying the DOM or JavaScript of other components.
Example: A component named
myComponent
cannot directly access the DOM elements or variables of another component namedyourComponent
.
Secure Wrappers:
Locker Service wraps standard browser objects (like
window
,document
, andelement
) with secure versions to prevent unsafe operations.Example: If you try to access
document.cookie
directly, Locker Service will block it unless explicitly allowed.
Strict Content Security Policy (CSP):
Locker Service enforces CSP to prevent cross-site scripting (XSS) and other security vulnerabilities.
JavaScript Restrictions:
Certain JavaScript features, like
eval()
andFunction()
, are disabled to prevent code injection attacks.
How It Impacts LWC:
Lightning Locker Service has a significant impact on how you develop and debug Lightning Web Components (LWC). Here’s how:
1. Access to Global Objects
- Locker Service restricts access to global objects like
window
anddocument
. Instead, you must use secure wrappers provided by Salesforce. Example:
- Locker Service restricts access to global objects like
// Without Locker Service
window.location.href = 'https://example.com'; // This will fail
// With Locker Service
import { NavigationMixin } from 'lightning/navigation';
// Use NavigationMixin to navigate safely
2. Component Encapsulation
Locker Service ensures that one component cannot access the DOM or JavaScript of another component, even if they are on the same page.
Example:
// This will fail because Locker Service prevents cross-component DOM access
const otherComponentElement = this.template.querySelector('c-other-component');
3. Strict Mode Enforcement
LWC runs in strict mode by default, which means you cannot use undeclared variables or other unsafe JavaScript practices.
Example:
x = 10; // This will throw an error in strict mode
let x = 10; // Correct way
4. Limited Access to Third-Party Libraries
- Locker Service restricts the use of third-party libraries that rely on unrestricted access to the DOM or global objects.
- Example: Libraries like jQuery may not work as expected unless they are compatible with Locker Service.
22. How does child-to-parent communication work in LWC?
Child components communicate with parent components using Custom Events.
Steps for "Child to Parent" Communication
1. Create a Custom Event in the Child LWC Component and Dispatch it to the Parent LWC Component:
- Use the CustomEvent constructor to create an event.
Include any necessary data in the
detail
property of the event.- Dispatch the event using this.dispatchEvent.
Example:
Child Component (childComponent.js)
import { LightningElement } from 'lwc';
export default class ChildComponent extends LightningElement {
handleButtonClick() {
// Create a custom event
const event = new CustomEvent('notifyparent', {
detail: { message: 'Hello from the child component!' }
});
// Dispatch the event
this.dispatchEvent(event);
}
}
Child Component HTML (childComponent.html)
2. Listen for the Event in the Parent Component:
- Use the
on
directive in the parent component’s HTML to listen for the custom event. Define a handler method in the parent component’s JavaScript to process the event and its payload.
- Use the
Example: Parent Component (parentComponent.js)
import { LightningElement } from 'lwc';
export default class ParentComponent extends LightningElement {
messageFromChild;
handleChildNotification(event) {
// Access the event payload
this.messageFromChild = event.detail.message;
}
}
Example: Parent Component HTML (parentComponent.html)
Message from child: {messageFromChild}
How It Works?
The child component dispatches a custom event (
notifyparent
) when the button is clicked.The parent component listens for this event using the
onnotifyparent
directive.When the event is detected, the parent component’s
handleChildNotification
method is triggered.The parent component accesses the event payload (
event.detail.message
) and updates its reactive property (messageFromChild
).
Key Points to Remember
Event Naming:
Use lowercase event names (e.g.,
notifyparent
) to follow DOM event naming conventions.Avoid using camelCase or PascalCase for event names.
Event Payload:
The
detail
property is used to pass data from the child to the parent.Keep the payload simple and avoid passing complex objects.
Event Bubbling:
By default, events bubble up the DOM tree. If you want to stop bubbling, use
event.stopPropagation()
in the child component.
Event Composition:
Use
composed: true
in the event constructor if you need the event to cross shadow DOM boundaries (rarely needed in LWC).
23. Explain the concept of "Custom Event" in LWC?
A CustomEvent in LWC is used to send data or notifications from a ‘Child LWC Component’ to a ‘Parent LWC Component’.
Key Points:
1. Create an Event in Child Component:
- Use the CustomEvent constructor to create the event.
- Optionally, include data in the event using the detail property
Example:
const event = new CustomEvent('myevent', { detail: 'Hello Parent!' });
2. Dispatch the Event from Child Component:
- Use this.dispatchEvent(event) to send the event from the child to the parent.
Example:
this.dispatchEvent(event);
3. Handle the Event in Parent Component:
- The parent listens for the event and handles it using a method.
Example in Parent HTML:
Example in Parent JS:
handleMyEvent(event) {
console.log(event.detail); // Access data sent from the child
}
In Simple Words:
A CustomEvent lets the Child LWC Component send messages or data to the Parent LWC Component, making it easy to communicate between components.
24. How do you handle form validation in LWC?
Form validation in LWC ensures that – users provide correct and complete input before submitting a form.
Various Ways to Validate a Form in LWC:
HTML5 Validation:
Use attributes likerequired
,min
,max
, andpattern
for basic validation.JavaScript Validation:
Implement custom logic in JavaScript for complex rules.Custom Error Messages:
UsesetCustomValidity()
to display user-friendly errors.SLDS Styling:
Apply Lightning Design System classes for error messages and styling.Cross-Field Validation:
Validate interdependent fields (e.g., password matching) in JavaScript.Reset Form:
Clear fields after successful submission.Lightning Data Service (LDS):
Use LDS for record-based validation and saving.
25. What is Lightning Data Service (LDS), and how is it used in LWC?
Lightning Data Service (LDS) is a built-in tool in Salesforce that allows Lightning Web Components (LWC) to read, create, update, and delete records without writing Apex code.
It provides a caching mechanism to improve performance and reduce server calls.
Key Features of LWC
No Apex Required:
Fetch and manipulate records directly in JavaScript.Automatic Caching:
Reduces redundant server calls.Real-Time Updates:
Automatically refreshes data when records are modified.Security:
Enforces field-level security and sharing rules.
How Is It Used in LWC?
LDS is used through wire adapters and methods to fetch, create, update, or delete records.
1. Fetching Records:
Use the @wire decorator with LDS adapters like getRecord to retrieve record data.
Example:
import { LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi'; // here we are using getRecord adapter to retrieve salesforce record to LWC component.
export default class MyComponent extends LightningElement {
@wire(getRecord, { recordId: '001...', fields: ['Account.Name'] })
account;
}
2. Saving or Updating Records:
Use LDS methods like updateRecord or createRecord.
Example:
import { updateRecord } from 'lightning/uiRecordApi';
handleUpdate() {
const fields = { Id: '001...', Name: 'Updated Name' };
const recordInput = { fields };
updateRecord(recordInput).then(() => console.log('Record updated'));
}
3. Deleting Records:
Use the ‘deleteRecord’ method to delete a record.
Benefits of LDS
Simplified Code: No need for Apex controllers.
Improved Performance: Caching reduces server calls.
Real-Time Sync: Automatically updates data across components.
When to Use LDS
Fetching or updating a single record.
Displaying record details without custom logic.
Reducing Apex dependencies for simple CRUD operations.
26. How do you call an Apex method imperatively in LWC?
Calling an Apex method imperatively in LWC means invoking the method on demand (e.g., when a button is clicked) rather than automatically when the component loads.
This is done using JavaScript.
Steps to Call Apex Method Imperatively:
1. Import the Apex Method:
- Use @salesforce/apex to import the Apex method.
import apexMethodName from '@salesforce/apex/Namespace.ClassName.apexMethodName';
2. Call the Method in JavaScript:
- Use JavaScript to call the method imperatively (e.g., in a button click handler).
handleClick() {
getAccounts()
.then((result) => {
console.log('Accounts:', result);
})
.catch((error) => {
console.error('Error:', error);
});
}
3. Handle the Response:
- Use .then() for success and .catch() for error handling.
In Simple Words:
To call an Apex method imperatively:
- Import it in the .js file.
- Call it like a function.
- Use .then() to get the result and .catch() to handle errors.
Check Out the below post, to learn more about Calling Apex by using Imperative Way in Salesforce.
27. What is the @wire decorator, and how does it differ from imperative Apex calls?
The @wire
decorator in Lightning Web Components (LWC) is used to automatically fetch data from Salesforce (e.g., using Apex methods or Lightning Data Service) and automatically update the component when the data changes.
It simplifies data binding and reduces boilerplate code.
Key Features of @wire:
Reactive Data Binding:
Automatically updates the component when the data changes.Declarative Syntax:
Fetch data without writing imperative JavaScript.Supports Apex and LDS:
Can call Apex methods or use Lightning Data Service (e.g.,getRecord
).Error Handling:
Provides a built-in mechanism to handle errors.
Example:
import { LightningElement, wire } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class Example extends LightningElement {
@wire(getAccounts)
accounts;
}
Difference Between @wire and Imperative calls
Feature | @wire Decorator | Imperative Apex Calls |
---|---|---|
Data Fetching | Automatic and reactive | Manual (on-demand) |
Syntax | Declarative (uses @wire ) | Imperative (uses JavaScript functions) |
Use Case | Fetch data when the component loads | Fetch data on user interaction (e.g., button click) |
Reactivity | Automatically updates when data changes | Requires manual updates |
Error Handling | Built-in (uses error property) | Manual (using .catch() ) |
Performance | Optimized with caching (for LDS) | No caching (unless implemented manually) |
When to Use @wire:
Fetching data when the component loads.
Automatically updating the UI when data changes.
Simplifying code with declarative data binding.
When to Use Imperative Calls:
Fetching data on user interaction (e.g., button click).
Performing actions like saving or updating records.
Avoiding unnecessary server calls when the component loads.
In Simple Words:
- Use @wire for automatic and real-time data updates.
- Use imperative calls when you need to control when and how the Apex method runs.
Check Out the below post, to learn more about the – Difference between @wire and Imperative way of calling Apex class in LWC
28. What are public properties in LWC, and how are they defined?
This is a tricky question related to the communication from Parent to Child component.
Public properties in LWC are those variables or properties in a child component that can be exposed to Parent LWC Components, so that Parent LWC Components can pass values to it.
How to Define Public Properties?
- Use the @api decorator to make a property public.
- These properties can be accessed and updated by the parent component.
Example:
Child Component JS (childComponent.js)
import { LightningElement, api } from 'lwc';
export default class ChildComponent extends LightningElement {
@api message; // Public property
}
Child Component HTML (childComponent.html)
{message}
Parent Component HTML (parentComponent.html)
Key Points:
@api
: Marks a property as public.Reactive: Changes to public properties automatically update the component.
Parent-Child Communication: Used to pass data from parent to child components.
Use Cases:
Passing configuration data to child components.
Making components reusable with customizable properties.
Enabling parent-child communication.
In Simple Words:
Public properties are those properties in a child component which are marked with the @api decorator, allowing the parent component to send data to the child.
29. How do you debug LWC components?
There are different ways which a developer can debug any LWC component.
1. Use Browser Developer Tools:
Open Chrome DevTools (F12 or right-click → Inspect).
Use the Console tab to view logs and errors.
Use the Sources tab to set breakpoints and step through JavaScript code.
2. Use console.log:
- Add console.log() statements in your JavaScript code to track variable values or flow.
Example:
handleClick() {
console.log('Button clicked');
console.log('Current value:', this.value);
}
3. Enable Debug Mode in Salesforce:
- Go to Setup > Debug Mode for Lightning Components and enable it for your user.
4. Use try...catch:
- Wrap code in try…catch blocks to handle and log errors.
Example:
try {
// Your code
} catch (error) {
console.error('Error:', error);
}
5. Check Network Tab:
- Use the Network tab in DevTools to monitor API calls or resource loading.
6. Lightning Inspector Extension:
- Install the Salesforce Lightning Inspector browser extension for advanced debugging.
In Simple Words:
Use console.log() and debugger for JavaScript debugging.
Leverage browser DevTools for logs, network requests, and HTML/CSS inspection.
Enable Salesforce Debug Mode and check Apex logs for backend issues.
30. What is the difference between import and export in LWC?
Both import and export keywords are used in Javascript file while building a LWC component.
Below is the reason, why import and export keywords are used:
1. import:
- Used to bring functionality or data from another file into the current file.
- Example: Importing methods, classes, or constants.
import { LightningElement } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
2. export:
- Used to share methods, classes, or constants from one file so they can be used in other files.
- Example: Exporting a class or function.
export default class MyComponent extends LightningElement { }
Key Difference:
- Import :Brings code into your component.
- Export : Shares code with other components or files.
31. How do you handle errors in LWC?
There are several ways to handle errors in LWC. Some of them are:
1. Use .catch() for Imperative Apex Calls
Catch errors when calling Apex methods imperatively.
import { LightningElement } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
handleLoadAccounts() {
getAccounts()
.then((result) => {
console.log('Accounts:', result);
})
.catch((error) => {
console.error('Error:', error); // Handle errors
});
}
}
2. Use error Property with @wire:
For @wire calls, check the error property to handle errors.
import { LightningElement, wire } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts) accounts;
get errorMessage() {
return this.accounts.error ? this.accounts.error.body.message : '';
}
}
3. Show Error Messages with 'lightning/platformShowToastEvent'
Display error messages to users using toast notifications.
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
handleLoadAccounts() {
getAccounts()
.then((result) => {
console.log('Accounts:', result);
})
.catch((error) => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: error.body.message,
variant: 'error',
}),
);
});
}
}
4. Validate Inputs
Use JavaScript to validate user inputs and show errors if invalid.
handleInputChange(event) {
const inputValue = event.target.value;
if (!inputValue) {
this.error = 'Input is required';
} else {
this.error = '';
}
}
5. Check for Null or Undefined Values
Avoid runtime errors by checking for null or undefined values.
if (this.accounts && this.accounts.data) {
console.log('Accounts:', this.accounts.data);
} else {
console.error('No accounts found');
}
Summary
Use
.catch()
for imperative Apex calls.Check the
error
property with@wire
.Show error messages using
ShowToastEvent
.Validate inputs and check for null/undefined values.
32. Explain how slots work in LWC.
Slots are placeholder in Child LWC component’s HTML file, where Parent LWC component can insert HTML content to it.
They make the LWC components more flexible by letting the parent component define some parts of the child component’s content.
Types of Slots
1. Default Slot:
If the parent provides content without a
slot
attribute, it goes into the default slot.If no content is provided, the fallback content is displayed.
Example:
Child Component (child.html):
Parent Component (child.html):
This is passed from the parent.
2. Named Slot:
The parent uses the
slot
attribute to specify which named slot the content should go into.If no content is provided for a named slot, its fallback content is displayed.
Example:
Child Component (child.html):
Parent Component (child.html):
Header Content
Default Content
Benefits of Slots
Flexibility: Allows dynamic content insertion.
Reusability: Makes components more versatile.
Fallback Content: Provides default content if no content is passed.
In Simple Words
- Slot: A placeholder in the child component where the parent can insert content.
Default Slot:
<slot>
for general content.Named Slots:
<slot name="slotName">
for targeted content.Fallback Content: Default content inside a slot.
Slots are a powerful feature in LWC for creating flexible and reusable components! 🚀
33. What are getters and setters in LWC, and how are they used?
Getters and setters are special methods in JavaScript that allow you to control access to a property. In LWC, they are often used to:
Compute dynamic values (getters).
Validate or modify values before setting them (setters).
Getters
Purpose: Compute or derive a value dynamically.
Syntax: Use the
get
keyword.Example:
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
firstName = 'John';
lastName = 'Doe';
// Getter to compute full name
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
Usage in HTML:
Full Name: {fullName}
Setters
Purpose: Validate or modify a value before assigning it to a property.
Syntax: Use the
set
keyword.Example:
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
_age;
// Setter to validate age
set age(value) {
if (value < 0) {
console.error('Age cannot be negative');
} else {
this._age = value;
}
}
// Getter to retrieve age
get age() {
return this._age;
}
}
Usage in JavaScript:
this.age = 25; // Valid
this.age = -5; // Logs error: "Age cannot be negative"
Combining Getters and Setters
You can use both together to create a controlled property.
Example:
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
_price = 0;
// Setter to validate price
set price(value) {
if (value < 0) {
console.error('Price cannot be negative');
} else {
this._price = value;
}
}
// Getter to format price
get price() {
return `$${this._price}`;
}
}
Usage in JavaScript:
this.price = 100; // Sets _price to 100
console.log(this.price); // Outputs "$100"
this.price = -50; // Logs error: "Price cannot be negative"
Benefits of Getters and Setters
Dynamic Values: Compute values on the fly.
Validation: Ensure data integrity.
Encapsulation: Hide internal logic from the user.
Summary
Getters: Compute or derive values dynamically.
Setters: Validate or modify values before setting them.
Use Cases: Dynamic properties, data validation, and encapsulation.
By using getters and setters, you can create more robust and flexible LWC components! 🚀
34. How can you use template loops (for:each) in LWC?
Template loops in LWC allow you to iterate over a list of items and render them dynamically in the HTML.
The for:each directive is used to loop through an array and generate content for each item.
Key Concepts
for:each
Directive:Iterates over an array.
Requires a unique
key
for each item to help LWC track changes efficiently.
for:item
Directive:Represents the current item in the loop.
key
Attribute:A unique identifier for each item (e.g.,
Id
orkey={uniqueId}
).
Example using for:each
JavaScript (myComponent.js)
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
contacts = [
{ Id: 1, Name: 'John Doe', Email: 'john@example.com' },
{ Id: 2, Name: 'Jane Smith', Email: 'jane@example.com' },
{ Id: 3, Name: 'Alice Johnson', Email: 'alice@example.com' },
];
}
HTML (myComponent.html)
-
Name: {contact.Name}, Email: {contact.Email}
How It Works
for:each={contacts}
:Loops through the
contacts
array.
for:item="contact"
:Represents the current item in the loop (e.g.,
contact
).
key={contact.Id}
:Provides a unique identifier for each item to help LWC track changes.
Nested Loops
You can also use nested loops to iterate over multi-dimensional arrays.
Example: Nested Loop
contacts = [
{
Id: 1,
Name: 'John Doe',
Emails: ['john@example.com', 'john.doe@work.com'],
},
{
Id: 2,
Name: 'Jane Smith',
Emails: ['jane@example.com'],
},
];
-
Name: {contact.Name}
- Email: {email}
Key Points
for:each
: Iterates over an array.for:item
: Represents the current item.key
: Unique identifier for each item (required).Nested Loops: Use multiple
for:each
directives for nested arrays.
Summary
Use
for:each
to loop through arrays and render dynamic content.Always include a
key
for efficient rendering.Nested loops allow you to handle complex data structures.
Template loops are a powerful feature in LWC for creating dynamic and reusable components! 🚀
35. What is the purpose of the key attribute in template loops?
The key attribute in LWC template loops (for:each) is used to uniquely identify each item in a list.
It helps LWC efficiently track and manage changes to the list, such as additions, deletions, or reordering.
Why is the key Attribute Important?
Efficient Rendering:
LWC uses the
key
to determine which items have changed, been added, or been removed.This minimizes unnecessary re-rendering of the entire list, improving performance.
Consistent State:
Ensures that the correct item is updated or removed, even if the list order changes.
Avoiding Bugs:
Without a
key
, LWC may incorrectly associate DOM elements with list items, leading to unexpected behaviour.
Example: Using the key Attribute
JavaScript (myComponent.js)
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
contacts = [
{ Id: 1, Name: 'John Doe', Email: 'john@example.com' },
{ Id: 2, Name: 'Jane Smith', Email: 'jane@example.com' },
{ Id: 3, Name: 'Alice Johnson', Email: 'alice@example.com' },
];
}
HTML (myComponent.html)
-
Name: {contact.Name}, Email: {contact.Email}
Key Points About 'key'
Unique Identifier:
The
key
must be unique within the list (e.g.,Id
or a unique combination of properties).
Static Value:
The
key
should not change during the component’s lifecycle. Avoid using indexes or random values.
Required for Lists:
Always include a
key
when usingfor:each
to avoid rendering issues.
What Happens Without a key?
Performance Issues: LWC may re-render the entire list instead of just the changed items.
Incorrect Updates: DOM elements may not correctly reflect the underlying data, leading to bugs.
Example: Using Index as key (Not Recommended)
-
Name: {contact.Name}, Email: {contact.Email}
Summary
- The
key
attribute is essential for efficient and accurate rendering of lists in LWC. Use a unique and stable identifier (e.g.,
Id
) for each item.Avoid using indexes or random values as
key
.
- The
By using the key
attribute correctly, you can ensure optimal performance and avoid bugs in your LWC components! 🚀
key={item.id}: Ensures each item has a unique identifier.
36. How can you use conditional rendering (if:true/if:false) in LWC?
Conditional rendering in LWC allows you to show or hide elements based on a condition.
This is done using the if:true and if:false directives in the HTML template.
Key Concepts
if:true
Directive:Renders the element if the condition is
true
.
if:false
Directive:Renders the element if the condition is
false
.
Dynamic Rendering:
The element is added or removed from the DOM based on the condition.
Example: Using if:true and if:false
JavaScript (myComponent.js)
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
isVisible = true;
isError = false;
}
HTML (myComponent.html)
This content is visible!
An error occurred!
No errors found.
How It Works
if:true={condition}
:The element is rendered only if the condition evaluates to
true
.
if:false={condition}
:The element is rendered only if the condition evaluates to
false
.
Dynamic Updates:
If the condition changes, the element is automatically added or removed from the DOM.
Example: Toggle Visibility with a Button
JavaScript (myComponent.js)
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
isVisible = true;
toggleVisibility() {
this.isVisible = !this.isVisible;
}
}
HTML (myComponent.html)
This content is visible!
Key Points
Use
if:true
for Positive Conditions:Render content when a condition is
true
.
Use
if:false
for Negative Conditions:Render content when a condition is
false
.
Avoid Complex Logic in Templates:
Keep conditions simple and handle complex logic in JavaScript.
Example: Combining if:true with Loops
JavaScript (myComponent.js)
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
contacts = [
{ Id: 1, Name: 'John Doe', IsActive: true },
{ Id: 2, Name: 'Jane Smith', IsActive: false },
{ Id: 3, Name: 'Alice Johnson', IsActive: true },
];
}
HTML (myComponent.html)
-
Name: {contact.Name}
(Active)
(Inactive)
Summary
Use
if:true
to render content when a condition istrue
.Use
if:false
to render content when a condition isfalse
.Combine conditional rendering with loops for dynamic and flexible UIs.
37. How does event bubbling work in LWC?
Event bubbling is a mechanism in which an event propagates upwards through the DOM hierarchy, from the target element to its parent elements.
In LWC, this allows parent components to handle events triggered by child components.
In Lightning Web Component (LWC), event bubbling works like this:
- When an event is triggered on a child element, it first executes any event handlers on that element (event target).
- The event then “bubbles up” through the DOM tree, triggering event handlers on parent elements in sequence, all the way up to the root.
For Example:
- You click a button inside a child component.
- The event fires on the button and “bubbles” to its parent components, one by one.
If you want to stop bubbling, use event.stopPropagation() in your event handler.
This is useful for controlling how events are handled across components in LWC.
38. What is the role of bubbles and composed in event propagation?
In LWC, bubbles and composed control how events propagate through the DOM
1. bubbles:
What it does: Determines whether the event bubbles up through the DOM hierarchy.
Default value:
false
.When to use: Set
bubbles: true
if you want the event to propagate to parent components.Example:
const event = new CustomEvent('myevent', {
bubbles: true, // Event will bubble up
detail: { message: 'Hello!' }
});
this.dispatchEvent(event);
2. composed:
What it does: Determines whether the event can cross shadow DOM boundaries.
Default value:
false
.When to use: Set
composed: true
if you want the event to be heard outside the shadow DOM (e.g., in parent components).Example:
const event = new CustomEvent('myevent', {
bubbles: true,
composed: true, // Event can cross shadow DOM
detail: { message: 'Hello!' }
});
this.dispatchEvent(event);
Together, they decide where the event can travel.
For example, to make an event accessible to parent components, you need bubbles: true and composed: true.
Key Differences:
Property | Purpose | Example Use Case |
---|---|---|
bubbles | Allows event to bubble up to parent elements. | Communicating from child to parent |
composed | Allows event to cross shadow DOM boundaries. | Communicating outside the component’s DOM |
For Example: Using bubbles and composed
Child Component (childComponent.js)
import { LightningElement } from 'lwc';
export default class ChildComponent extends LightningElement {
handleClick() {
const event = new CustomEvent('childclick', {
bubbles: true, // Event bubbles up
composed: true, // Event crosses shadow DOM
detail: { message: 'Button clicked!' }
});
this.dispatchEvent(event);
}
}
Parent Component (parentComponent.html)
Parent Component JavaScript (parentComponent.js)
import { LightningElement } from 'lwc';
export default class ParentComponent extends LightningElement {
handleChildClick(event) {
console.log('Event received:', event.detail.message);
}
}
Summary
bubbles : Controls whether the event bubbles up to parent components.
composed : Controls whether the event can cross shadow DOM boundaries.
Use both properties to control how events propagate in your LWC components.
By understanding bubbles & composed, you can fine-tune event propagation for better component communication! 🚀
39. What is the by default behaviour of bubbles and composed in event propagation?
When you create a custom event in LWC, the bubbles
and composed
properties have default values that determine how the event propagates. Here’s what you need to know:
1. bubbles
Default Value:
false
Behaviour: By default, the event does not bubble up through the DOM hierarchy.
What it means: The event will only trigger on the element where it was dispatched and will not propagate to parent elements.
2. composed
Default Value:
false
Behaviour: By default, the event cannot cross shadow DOM boundaries.
What it means: The event will only be heard within the same shadow DOM tree and will not propagate outside the component.
Why Defaults Matter:
This default behaviour ensures that:
- Events are restricted to the component where they are triggered, providing isolation.
- Developers have to explicitly enable bubbling and crossing Shadow DOM boundaries, giving better control over event propagation.
Example: Default Behaviour
Child Component (childComponent.js)
import { LightningElement } from 'lwc';
export default class ChildComponent extends LightningElement {
handleClick() {
// Default behavior: bubbles=false, composed=false
const event = new CustomEvent('childclick', {
detail: { message: 'Button clicked!' }
});
this.dispatchEvent(event);
}
}
Parent Component (parentComponent.html)
Parent Component JavaScript (parentComponent.js)
import { LightningElement } from 'lwc';
export default class ParentComponent extends LightningElement {
handleChildClick(event) {
console.log('Event received:', event.detail.message);
}
}
What Happens with Default Behavior?
bubbles: false:
The
childclick
event will not bubble up to the parent component.The parent’s
handleChildClick
method will not be triggered.
composed: false
The
childclick
event will not cross the shadow DOM boundary.Even if
bubbles
weretrue
, the event would not reach the parent component.
How to Change the Behaviour?
To allow the event to bubble up and/or cross shadow DOM boundaries, explicitly set bubbles and composed to true
const event = new CustomEvent('childclick', {
bubbles: true, // Event bubbles up
composed: true, // Event crosses shadow DOM
detail: { message: 'Button clicked!' }
});
this.dispatchEvent(event);
Summary
bubbles: Default is false (event does not bubble up).
composed: Default is false (event does not cross shadow DOM).
To enable event propagation, set bubbles: true and/or composed: true.
By understanding the default behavior, you can control how events propagate in your LWC components! 🚀
40. How can you handle DOM manipulation in LWC?
In LWC, you handle DOM manipulation carefully because the framework emphasizes declarative rendering. Here’s how you can do it safely and effectively:
1. Use Template References (@api Decorator)
Assign a template reference using data-id or querySelector to access DOM elements.
Example:
Hello!
connectedCallback() {
const myDiv = this.template.querySelector('[data-id="myDiv"]');
myDiv.style.color = 'blue'; // Manipulate DOM element
}
2. Avoid Direct DOM Manipulation
Instead of manipulating the DOM directly, update properties or state variables, and let LWC re-render the DOM automatically.
Example:
{message}
message = 'Hello!';
updateMessage() {
this.message = 'Updated!';
}
3. Use LifeyCycle Hooks
Manipulate the DOM only within LWC lifecycle hooks like:
- connectedCallback: When the component is added to the DOM.
- renderedCallback: After the component is rendered.
4. Work with Shadow DOM
Use this.template.querySelector or querySelectorAll to access elements inside the component’s Shadow DOM.
Key Tip
Avoid Direct DOM Manipulation: Use reactive properties and template directives.
Access DOM Safely: Use
this.template.querySelector()
orthis.template.querySelectorAll()
.Update Styles and Attributes: Use
classList
andsetAttribute
.
By following these practices, you can safely handle DOM manipulation in LWC while maintaining encapsulation and reactivity! 🚀
Conclusion
In this second installment of our LWC Interview Questions series, we’ve covered questions 21 to 40, diving deeper into advanced topics like event handling, DOM manipulation, conditional rendering, and template loops. These questions are designed to help you master the nuances of Lightning Web Components and prepare for your next Salesforce developer interview.
Stay tuned for the next blog in this series, where we’ll explore even more advanced topics and interview questions. Keep practicing, and you’ll be well on your way to becoming an LWC expert! 🚀