Dynamic components in lightning web components (lwc)

The Salesforce Winter '24 release introduced dynamic components for Lightning web components (lwc). Salesforce developers can leverage dynamic components to instantiate LWC components dynamically at runtime.

How to use dynamic components

To implement dynamic components in lightning web components, utilize the new lwc:component tag with the lwc:is attribute.

lwc:component is a placeholder tag and will be replaced with the actual component at run time

lwc:is directive a required attribute and it signals the compiler that component is unknown at compile time

Below is a sample html, js and metadata file that implements a dynamic component
html file
<div class="container">
    <lwc:component lwc:is={dynamicInstance}>
    </lwc:component>
</div>

*dynamicInstance is the dynamic component that is resolved at run time

javascript file
import { LightningElement } from "lwc";
export default class extends LightningElement {
    dynamicInstance;
    connectedCallback() {
    import("c/accountCompactDetails")
        .then(({ default: ctor }) => (this.dynamicInstance = ctor))
        .catch((err) => 
}
        
metadata file

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <capabilities>
        <capability>lightning__dynamicComponent</capability>
    </capabilities>
</LightningComponentBundle>
        

To use dynamic component, the component must include 'lightning__dynamicComponent' capability in the component configuration file and sets the api version to 59 or higher

Runtime Behavior

When a lightning component is rendered, the dynamic component is mounted in the DOM and when lwc:is changed, the component will be unmounted. The new component will be mounted instead.

To select a dynamic component, use lwc:ref directive or any attribute like class name attached to the component.

In order to identify dynamic component is loaded to DOM:
  • Use connected callback in the dynamic component
  • Or use renderedCallback on the parent component

The child elements can also be added in a dynamic component. The dynamic component will be rendered first and then the child components.

An example below:

<div class="container">
    <lwc:component lwc:is={dynamicInstance}>
        <div>
            <p> End of dynamic component</p>
        </div>
    </lwc:component>
</div>

Things to consider

As the dynamic component is unknown at compile time, the framework does not prefetch the dynamic modules. This may cause a slight delay at run time.

The dynamic nature of the component causes the component hierarchy to be re-rendered which may lead to performance issues.

Complete code example

Here we have a dynamic component that will show the account full / compact view on click of a button. The onclick action on the button will rerender the component and the respective view mode will display the details.

<template>
    <div class="slds-clearfix">
        <div class="slds-float_right">
            <lightning-button variant="brand" label={btnLabel} title="View details" onclick={handleViewDetails} class="slds-m-left_x-small"></lightning-button>
        </div>
    </div>
    <div class="slds-p-around_medium">
        <lwc:component lwc:is={dynamicInstance} record-id={recordId}>
        </lwc:component>
    </div>
</template>
import { LightningElement,api } from 'lwc';
export default class AccountInfo extends LightningElement {
    @api recordId;
    dynamicInstance;
    showDetails = false;
    get btnLabel(){
        return this.showDetails?'View account compact page':'View account full page';
    }

    connectedCallback(){
        import("c/accountCompactDetails")
                .then(({ default: ctor }) => (this.dynamicInstance = ctor))
                .catch((err) => 
    }

    handleViewDetails(){
        if(this.showDetails){
            import("c/accountCompactDetails")
                .then(({ default: ctor }) => (this.dynamicInstance = ctor))
                .catch((err) => 
            this.showDetails = false;
        }
        else{
            import("c/accountDetails")
                .then(({ default: ctor }) => (this.dynamicInstance = ctor))
                .catch((err) => 
            this.showDetails = true;
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
    <capabilities>
        <capability>lightning__dynamicComponent</capability>
    </capabilities>
</LightningComponentBundle>

Complete code in github

Demo

dynamic components in lwc demo

What is Decodeforce?

Decodeforce is a dedicated platform aimed at helping Salesforce developers improve their Apex coding skills by solving real-world programming challenges

Solve a number of practice scenarios in DML, SOQL, trigger and many more on Decodeforce.

To know more click the Get started button below