Pages

Sunday, September 26, 2021

Lightning Web Components Interview Questions- Part 2

11. How can we access elements in the controller?

We have two methods available: this.template.querySelector() and this.template.querySelectorAll().

<!-- example.html -->
<template>
   <div>First <slot name="task1">Task 1</slot></div>
   <div>Second <slot name="task2">Task 2</slot></div>
</template>
// example.js
import { LightningElement } from 'lwc';

export default class Example extends LightningElement {
    renderedCallback() {
        this.template.querySelector('div'); // <div>First</div>
        this.template.querySelector('span'); // null
        this.template.querySelectorAll('div'); // [<div>First</div>, <div>Second</div>]
    }
}

12. What is the default value of a Boolean property?

False. We should give a default value if we want to update the value later.

13. How can we load a third-party JavaScript (JS) library in Lightning Web Components (LWC)?

We have a few ways to load a third-party library:

  • Import the static resource: import resourceName from '@salesforce/resourceUrl/resourceName';
  • Import methods from the platformResourceLoader module: import { loadStyle, loadScript } from 'lightning/platformResourceLoader';
// libsD3.js
/* global d3 */
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import D3 from '@salesforce/resourceUrl/d3';
import DATA from './data';

export default class LibsD3 extends LightningElement {
    svgWidth = 400;
    svgHeight = 400;
    d3Initialized = false;

    renderedCallback() {
        if (this.d3Initialized) {
            return;
        }
        this.d3Initialized = true;

        Promise.all([
            loadScript(this, D3 + '/d3.v5.min.js'),
            loadStyle(this, D3 + '/style.css')
        ])
            .then(() => {
                this.initializeD3();
            })
            .catch(error => {
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error loading D3',
                        message: error.message,
                        variant: 'error'
                    })
                );
            });
    }

    initializeD3() {
        // some code
    }
}

A couple more methods are available here — load a single script without CSS:

loadScript(this, resourceName + '/lib.js')
    .then(() => { /* callback */ });

Load multiple files:

Promise.all([
    loadScript(this, resourceName + '/lib1.js'),
    loadScript(this, resourceName + '/lib2.js'),
    loadScript(this, resourceName + '/lib3.js')
]).then(() => { /* callback */ });

Note: whether a given third-party library works smoothly depends on your org’s client-side security architecture — see Question 21 below on Lightning Web Security, since it handles global objects and sandboxing differently than the older Lightning Locker.

14. Is it possible to call a third-party API from LWC JS, and what controls that access?

By default, browser-side JavaScript in LWC can’t make WebSocket connections or calls to third-party APIs. To allow it, the target domain must be added as a CSP Trusted Site in Setup — this is separate from Apex’s Remote Site Settings, which govern server-side callouts instead.

This is enforced by Salesforce’s client-side security architecture. Since Winter ’23, new orgs default to Lightning Web Security (LWS), which replaced the older Lightning Locker; LWS has been generally available for all orgs (LWC and Aura) since Summer ’23. LWS uses a JavaScript sandbox with “distortions” (rewriting risky APIs at runtime) instead of Locker’s secure wrapper objects, which makes it both more standards-compliant and generally faster, and it supports custom elements and third-party web components that Locker used to block outright. Whether a specific third-party library will “just work” in your component often depends on which of the two architectures your org is running.

15. How do you access a static resource?

Import it the same way as any static resource:

import resourceName from '@salesforce/resourceUrl/resourceName';

Then reference it in your component to load images, styles, or other static assets bundled in the resource.

16. How do you get the current User ID?

Import the Id property from the @salesforce/user scoped module:

import USER_ID from '@salesforce/user/Id';

This gives you the current running user’s Id directly, without needing an Apex callout.

17. How can we make changes to a component’s body after it’s rendered?

The renderedCallback() is unique to Lightning Web Components. Use it to perform logic after a component has finished the rendering phase.

This hook flows from child to parent. A component is usually rendered many times during the lifespan of an application. To use this hook for a one-time operation, use a boolean field like hasRendered to track whether renderedCallback() has already executed — the first time it runs, perform the one-time operation and set hasRendered = true; if hasRendered is already true, don’t perform the operation again.

18. What are the decorators in LWC?

@api — Public properties are reactive. If the value of a public property changes, the component rerenders. To expose a public property, decorate a field with @api. Public properties define the API for a component. To expose a public method, decorate it with @api as well — public methods are part of a component’s API, and owner/parent components can call JavaScript methods on child components to communicate down the containment hierarchy.

@track — Fields are reactive: if a field’s value changes, and the field is used in a template (or in a getter of a property used in a template), the component rerenders and displays the new value. There’s one specific use case for @track: when a field contains an object or an array, there’s a limit to the depth of changes that are tracked automatically, so decorate the field with @track to tell the framework to observe changes to the properties of an object or the elements of an array.

@wire — To read Salesforce data, Lightning web components use a reactive wire service. When the wire service provisions data, the component rerenders. Components use @wire in their JavaScript class to specify a wire adapter or an Apex method.

19. How do you call Apex from Lightning Web Components?

Import the Apex method using its fully qualified reference, then either wire it reactively or call it imperatively:

import getContactList from '@salesforce/apex/ContactController.getContactList';

Using @wire, the method is called automatically and the component rerenders when the data changes. Calling it imperatively (as a plain function returning a Promise) gives you more control over exactly when the call happens, such as inside a button click handler.

20. How can we use Lightning Web Components in Visualforce?

LWC can be embedded in a Visualforce page by wrapping it in an Aura component first (since Visualforce can only host Aura components directly), then embedding that Aura wrapper on the Visualforce page using the <apex:includeLightning /> tag and the $Lightning.use() / $Lightning.createComponent() JavaScript APIs.

21. What is Lightning Web Security (LWS), and how is it different from Lightning Locker?

Lightning Web Security is Salesforce’s current client-side security architecture for Lightning components, and it replaced the older Lightning Locker. Key differences relevant in an interview:

  • Locker isolated components using secure wrapper objects around window, document, and other globals, plus proxy objects — this blocked custom elements and most third-party web components outright, and could add runtime overhead.
  • LWS instead runs each namespace in its own JavaScript sandbox and uses “distortions” — rewriting how risky APIs behave at runtime — to prevent unsafe actions while allowing custom elements, third-party web components, and libraries that manipulate global objects, since those changes don’t leak across namespace sandboxes.
  • Adoption timeline: LWS became generally available in Spring ’22, is the default security architecture for all orgs created since Winter ’23, and became fully generally available for both LWC and Aura components across all orgs in Summer ’23.
  • Practical impact: LWS generally requires no code changes for well-behaved LWC, since existing components already follow secure coding conventions — but orgs with legacy Aura components or managed packages that rely on Locker’s specific wrapper behavior should test in a sandbox before enabling it, since Locker-era workarounds can behave differently once distortions apply instead.