Work with Custom Elements (Beta)

This feature is a Beta Service. Customer may opt to try such Beta Service in its sole discretion. Any use of the Beta Service is subject to the applicable Beta Services Terms provided at Agreements and Terms.

Third-party web components are web components that you can create using customElements.define(), resulting in custom elements you can reuse in an LWC app. You don't need to use custom elements with LWC unless you're working with third-party web components. For the purpose of this article, custom elements and third-party web components are interchangeable.

Lightning Web Security (LWS) must be enabled in the Salesforce org because Lightning Locker doesn’t support third-party web components.

A custom element must follow these characteristics.

  • Initialize the custom element using a constructor() via a class.
  • Use shadow DOM or light DOM. For shadow DOM, LWS supports the closed mode only.
  • Register the custom element within the CustomElementRegistry using customElements.define(name, constructor). The name must contain a hyphen and be unique on a page.

Using a <template> tag in your custom element is optional. You can create a <template> tag using document.createElement("template");. You can't use a nested <template> tag in your LWC HTML template.

In LWC, custom elements are only needed when you're working with third-party web components. When you implement a third-party web component in LWC, we recommend that you refer to that component's documentation for usage information.

Third-party web components contain a custom element definition, which extends the HTMLElement class. The custom element definition describes how to show the element and what to do when the element is added or removed.

The third-party web component behavior is described in lifecycle callbacks, such as in connectedCallback() or disconnectedCallback().

  • constructor()-Called when the custom element is initialized. It must call super() and can specify any pre-rendering processes like setting the content of the shadow.
  • connectedCallback()-Invoked when the custom element is connected to the DOM.
  • disconnectedCallback()-Invoked when the custom element is disconnected from the DOM.
  • observedAttributes()-Returns an array of attributes to observe.
  • attributeChangedCallback()-Invoked when an attribute is added, removed, or changed. Specify the attributes to observe in observeAttributes().
  • adoptedCallback()-Invoked when the custom element is moved to a new document.

In LWC, custom elements are only needed when you're working with third-party web components. When you implement a third-party web component in LWC, we recommend that you refer to that component's documentation for usage information.

Third-party web components contain a constructor to set up initial state and default values, set up event listeners, and create a shadow root.

To establish the prototype chain, call super() in the constructor. Attach a shadow root to the custom element using this.attachShadow(). LWS requires that the mode is set to closed. See How Lightning Web Security Compares to Lightning Locker.

In closed mode, the shadowRoot property returns null so you can’t use the shadowRoot to access and manipulate the shadow root of the element. When creating custom elements in closed mode, save the reference to the shadow root with a different variable, such as shadow or __shadowRoot.

To create the element's internal shadow DOM structure, append content using .innerHTML. This example defines the custom element outside of the LWC component lifecycle.

To work with the custom element's attributes and children, use connectedCallback() or renderedCallback() instead. For example, if you're creating elements and setting attributes on them, defer them to one of the lifecycle callbacks and use attributeChangedCallback() to define a callback when the attribute is changed. For more information, see the custom element specification.

Use the custom element in your LWC template with the lwc:external directive.

Here's an example to demonstrate the structure of a custom element. The example creates a button that increments the counter on its label when pressed.

To use the custom element in LWC, add it to your template using the lwc:external directive.

The component renders in the DOM like this. The button label ${this.count} is incremented each time it's clicked.

This example is similar to the previous example, but it watches the custom element's count attribute, using attributeChangedCallback() to define a callback when the attribute is changed.

Add the custom element tag to your LWC template.

See Also