20 Essential Salesforce LWC Interview Questions for Developers – Part 2

20 Essential Salesforce LWC Interview Questions for Developers – Part 2
Chinmaya By Chinmaya
39 Min Read

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

  1. 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 named yourComponent.

  2. Secure Wrappers:

    • Locker Service wraps standard browser objects (like windowdocument, and element) with secure versions to prevent unsafe operations.

    • Example: If you try to access document.cookie directly, Locker Service will block it unless explicitly allowed.

  3. Strict Content Security Policy (CSP):

    • Locker Service enforces CSP to prevent cross-site scripting (XSS) and other security vulnerabilities.

  4. JavaScript Restrictions:

    • Certain JavaScript features, like eval() and Function(), 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 and document. Instead, you must use secure wrappers provided by Salesforce.
    • Example:

				
					// 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)

				
					<template>
    <lightning-button label="Notify Parent" onclick={handleButtonClick}></lightning-button>
</template>
				
			

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.

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)

				
					<template>
    <c-child-component onnotifyparent={handleChildNotification}></c-child-component>
    <p>Message from child: {messageFromChild}</p>
</template>
				
			

How It Works?

    1. The child component dispatches a custom event (notifyparent) when the button is clicked.

    2. The parent component listens for this event using the onnotifyparent directive.

    3. When the event is detected, the parent component’s handleChildNotification method is triggered.

    4. The parent component accesses the event payload (event.detail.message) and updates its reactive property (messageFromChild).

Key Points to Remember

    1. Event Naming:

      • Use lowercase event names (e.g., notifyparent) to follow DOM event naming conventions.

      • Avoid using camelCase or PascalCase for event names.

    2. 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.

    3. Event Bubbling:

      • By default, events bubble up the DOM tree. If you want to stop bubbling, use event.stopPropagation() in the child component.

    4. 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:

				
					<c-child-component onmyevent={handleMyEvent}></c-child-component>
				
			

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:

    1. HTML5 Validation:
      Use attributes like requiredminmax, and pattern for basic validation.

    2. JavaScript Validation:
      Implement custom logic in JavaScript for complex rules.

    3. Custom Error Messages:
      Use setCustomValidity() to display user-friendly errors.

    4. SLDS Styling:
      Apply Lightning Design System classes for error messages and styling.

    5. Cross-Field Validation:
      Validate interdependent fields (e.g., password matching) in JavaScript.

    6. Reset Form:
      Clear fields after successful submission.

    7. 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

    1. No Apex Required:
      Fetch and manipulate records directly in JavaScript.

    2. Automatic Caching:
      Reduces redundant server calls.

    3. Real-Time Updates:
      Automatically refreshes data when records are modified.

    4. 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.
				
					<button onclick={handleClick}>Get Accounts</button>
				
			

In Simple Words:

To call an Apex method imperatively:

    1. Import it in the .js file.
    2. Call it like a function.
    3. 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 DecoratorImperative Apex Calls
Data Fetching Automatic and reactiveManual (on-demand)
SyntaxDeclarative (uses @wire)Imperative (uses JavaScript functions)
Use CaseFetch data when the component loadsFetch data on user interaction (e.g., button click)
ReactivityAutomatically updates when data changesRequires manual updates
Error HandlingBuilt-in (uses error property)Manual (using .catch())
PerformanceOptimized 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)

				
					<template>
    <p>{message}</p>
</template>
				
			

Parent Component HTML (parentComponent.html)

				
					<template>
    <c-child-component message="Hello from Parent!"></c-child-component>
</template>
				
			

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):

				
					<template>
    <div>
        <slot></slot>
    </div>
</template>
				
			

Parent Component (child.html):

				
					<template>
    <c-child>
        <p>This is passed from the parent.</p>
    </c-child>
</template>
				
			

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):

				
					<template>
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
</template>
				
			

Parent Component (child.html):

				
					<template>
    <c-child>
        <p slot="header">Header Content</p>
        <p>Default Content</p>
    </c-child>
</template>
				
			

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:

				
					<template>
    <p>Full Name: {fullName}</p>
</template>
				
			

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

    1. Dynamic Values: Compute values on the fly.

    2. Validation: Ensure data integrity.

    3. 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

    1. for:each Directive:

      • Iterates over an array.

      • Requires a unique key for each item to help LWC track changes efficiently.

    2. for:item Directive:

      • Represents the current item in the loop.

    3. key Attribute:

      • A unique identifier for each item (e.g., Id or key={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)

				
					<template>
    <ul>
        <template for:each={contacts} for:item="contact">
            <li key={contact.Id}>
                Name: {contact.Name}, Email: {contact.Email}
            </li>
        </template>
    </ul>
</template>
				
			

How It Works

    1. for:each={contacts}:

      • Loops through the contacts array.

    2. for:item="contact":

      • Represents the current item in the loop (e.g., contact).

    3. 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'],
    },
];
				
			
				
					<template>
    <ul>
        <template for:each={contacts} for:item="contact">
            <li key={contact.Id}>
                Name: {contact.Name}
                <ul>
                    <template for:each={contact.Emails} for:item="email">
                        <li key={email}>Email: {email}</li>
                    </template>
                </ul>
            </li>
        </template>
    </ul>
</template>
				
			

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?

    1. 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.

    2. Consistent State:

      • Ensures that the correct item is updated or removed, even if the list order changes.

    3. 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)

				
					<template>
    <ul>
        <template for:each={contacts} for:item="contact">
            <li key={contact.Id}>
                Name: {contact.Name}, Email: {contact.Email}
            </li>
        </template>
    </ul>
</template>
				
			

Key Points About 'key'

    1. Unique Identifier:

      • The key must be unique within the list (e.g., Id or a unique combination of properties).

    2. Static Value:

      • The key should not change during the component’s lifecycle. Avoid using indexes or random values.

    3. Required for Lists:

      • Always include a key when using for: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)

				
					<template>
    <ul>
        <template for:each={contacts} for:item="contact" for:index="index">
            <li key={index}> <!-- Avoid using index as key -->
                Name: {contact.Name}, Email: {contact.Email}
            </li>
        </template>
    </ul>
</template>
				
			

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.

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

    1. if:true Directive:

      • Renders the element if the condition is true.

    2. if:false Directive:

      • Renders the element if the condition is false.

    3. 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)

				
					<template>
    <!-- Render if isVisible is true -->
    <template if:true={isVisible}>
        <p>This content is visible!</p>
    </template>

    <!-- Render if isError is true -->
    <template if:true={isError}>
        <p class="error">An error occurred!</p>
    </template>

    <!-- Render if isError is false -->
    <template if:false={isError}>
        <p>No errors found.</p>
    </template>
</template>
				
			

How It Works

    1. if:true={condition}:

      • The element is rendered only if the condition evaluates to true.

    2. if:false={condition}:

      • The element is rendered only if the condition evaluates to false.

    3. 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)

				
					<template>
    <!-- Button to toggle visibility -->
    <lightning-button label="Toggle Visibility" onclick={toggleVisibility}></lightning-button>

    <!-- Render if isVisible is true -->
    <template if:true={isVisible}>
        <p>This content is visible!</p>
    </template>
</template>
				
			

Key Points

    1. Use if:true for Positive Conditions:

      • Render content when a condition is true.

    2. Use if:false for Negative Conditions:

      • Render content when a condition is false.

    3. 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)

				
					<template>
    <ul>
        <template for:each={contacts} for:item="contact">
            <li key={contact.Id}>
                Name: {contact.Name}
                <template if:true={contact.IsActive}>
                    <span> (Active)</span>
                </template>
                <template if:false={contact.IsActive}>
                    <span> (Inactive)</span>
                </template>
            </li>
        </template>
    </ul>
</template>
				
			

Summary

    • Use if:true to render content when a condition is true.

    • Use if:false to render content when a condition is false.

    • 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:

    1. When an event is triggered on a child element, it first executes any event handlers on that element (event target).
    2. 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:

    1. You click a button inside a child component.
    2. 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:

PropertyPurposeExample Use Case
bubbles   Allows event to bubble up to parent elements.   Communicating from child to parent
composedAllows 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)

				
					<template>
    <c-child-component onchildclick={handleChildClick}></c-child-component>
</template>
				
			

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:

    1. Events are restricted to the component where they are triggered, providing isolation.
    2. 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)

				
					<template>
    <c-child-component onchildclick={handleChildClick}></c-child-component>
</template>
				
			

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?

    1. bubbles: false:

      • The childclick event will not bubble up to the parent component.

      • The parent’s handleChildClick method will not be triggered.

    2. composed: false

      • The childclick event will not cross the shadow DOM boundary.

      • Even if bubbles were true, 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:

				
					<template>
    <div data-id="myDiv">Hello!</div>
</template>
				
			
				
					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:

				
					<template>
    <p>{message}</p>
    <button onclick={updateMessage}>Click Me</button>
</template>
				
			
				
					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() or this.template.querySelectorAll().

    • Update Styles and Attributes: Use classList and setAttribute.

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 handlingDOM manipulationconditional 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! 🚀

Share This Article
Follow:
Chinmaya is working as a Senior Consultant with a deep expertise in Salesforce. Holding multiple Salesforce certifications, he is dedicated to designing and implementing cutting-edge CRM solutions. As the creator of Writtee.com, Chinmaya shares his knowledge on educational and technological topics, helping others excel in Salesforce and related domains.
Leave a comment