Custom Elements in JavaScript

Custom Elements in JavaScript

Custom Elements in JavaScript

Custom Elements is one of the key features of the Web Components standard that allows developers to define new HTML elements. These custom elements can have their own behavior, lifecycle methods, and properties, just like standard HTML elements. You can create reusable components that encapsulate their own functionality, making them easy to share and integrate into different web applications.

What are Custom Elements?

Custom Elements are a way to define new HTML elements that can have custom behavior and appearance. They are defined by extending the base HTMLElement class and then defining specific lifecycle methods and properties.

How to Create a Custom Element

To create a custom element, you must:

  1. Define a class that extends HTMLElement.
  2. Define lifecycle methods (e.g., constructor, connectedCallback, disconnectedCallback, attributeChangedCallback).
  3. Register the custom element using customElements.define().

Basic Steps:

  1. Create a class that extends HTMLElement.
  2. Define custom behavior inside the class.
  3. Register the class as a custom element.

Custom Element Example: Basic Custom Element

Step 1: Create the Custom Element Class

class MyCustomElement extends HTMLElement { constructor() { super(); // Always call super() first // Create a shadow root this.attachShadow({ mode: 'open' }); // Add content to the shadow DOM this.shadowRoot.innerHTML = ` <style> p { color: blue; } </style> <p>This is a custom element!</p> `; } connectedCallback() { // Called when the element is added to the DOM console.log('My custom element is added to the page.'); } disconnectedCallback() { // Called when the element is removed from the DOM console.log('My custom element is removed from the page.'); } }

Step 2: Register the Custom Element

customElements.define('my-custom-element', MyCustomElement);

Step 3: Use the Custom Element in HTML

<my-custom-element></my-custom-element>
  • <my-custom-element></my-custom-element> is the custom HTML tag that we just created. When the page loads, the browser will recognize this tag and instantiate MyCustomElement class, rendering its content.

Custom Element Lifecycle Methods

Custom Elements have lifecycle methods that allow you to hook into the element’s lifecycle. These methods give you control over what happens when the element is added or removed from the DOM.

1. constructor()

  • Called when the element is created.
  • Used for initializing state, setting up event listeners, and attaching a shadow DOM.

2. connectedCallback()

  • Called when the element is inserted into the DOM.
  • Useful for setup like fetching data or adding event listeners.

3. disconnectedCallback()

  • Called when the element is removed from the DOM.
  • Can be used to clean up resources, such as removing event listeners.

4. adoptedCallback() (Optional)

  • Called when the element is moved to a new document (e.g., when the document is embedded in an iframe).
  • Use this to handle any changes that need to occur when the element is adopted into another document.

5. attributeChangedCallback()

  • Called when an observed attribute is added, changed, or removed.
  • You must also define the observedAttributes static getter to specify which attributes you want to observe.

Example: Custom Element with Lifecycle Methods

class CustomCard extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } // Lifecycle callback when element is connected to the DOM connectedCallback() { this.shadowRoot.innerHTML = ` <style> div { border: 1px solid #ccc; padding: 10px; border-radius: 5px; } </style> <div> <h2>${this.getAttribute('title')}</h2> <p>${this.getAttribute('content')}</p> </div> `; } // Lifecycle callback when element is removed from the DOM disconnectedCallback() { console.log('CustomCard removed'); } // Lifecycle callback when an observed attribute is changed static get observedAttributes() { return ['title', 'content']; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'title' || name === 'content') { this.shadowRoot.querySelector(`h2`).textContent = this.getAttribute('title'); this.shadowRoot.querySelector(`p`).textContent = this.getAttribute('content'); } } } // Define the custom element customElements.define('custom-card', CustomCard);

Usage

<custom-card title="Custom Card" content="This is a custom card!"></custom-card>

In this example:

  • We use connectedCallback() to add content when the element is inserted into the DOM.
  • We use attributeChangedCallback() to react to changes in the title or content attributes.
  • observedAttributes tells the browser which attributes to observe for changes.

Using Attributes with Custom Elements

You can observe and react to changes in the attributes of custom elements. This is done by defining the observedAttributes static getter and the attributeChangedCallback() method.

Example: Using Attributes

class CounterElement extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this._count = 0; } static get observedAttributes() { return ['count']; } connectedCallback() { this.shadowRoot.innerHTML = ` <style> button { font-size: 20px; } </style> <button>Count: ${this._count}</button> `; this.shadowRoot.querySelector('button').addEventListener('click', () => this.increment()); } attributeChangedCallback(name, oldValue, newValue) { if (name === 'count') { this._count = parseInt(newValue); this.shadowRoot.querySelector('button').textContent = `Count: ${this._count}`; } } increment() { this._count++; this.setAttribute('count', this._count); } } customElements.define('counter-element', CounterElement);

Usage:

<counter-element count="0"></counter-element>

When the count attribute changes, the attributeChangedCallback method will update the button text accordingly.

Custom Elements Best Practices

  1. Encapsulation: Use the Shadow DOM to encapsulate your element’s styles and internal structure. This helps prevent styles from leaking into or out of the component.

  2. Attribute Management: Use attributeChangedCallback() to handle changes in attributes dynamically. Avoid direct DOM manipulation inside the connectedCallback() to ensure the component can properly react to changes.

  3. Custom Events: You can dispatch custom events from your custom elements using the CustomEvent constructor. This allows your component to communicate with other parts of the application.

    const event = new CustomEvent('myCustomEvent', { detail: { message: 'Hello!' } }); this.dispatchEvent(event);
  4. Default Values: Consider providing default values for attributes that aren’t set by the user. This ensures that your component behaves consistently even when attributes are missing.

  5. Polyfills: While most modern browsers support custom elements, some older browsers (like Internet Explorer) do not. To ensure compatibility, you may need to use a polyfill, such as the Web Components Polyfill.

Summary

Custom Elements in JavaScript allow you to create reusable components by defining new HTML tags. These elements can have custom behavior, styles, and lifecycle methods, making them a powerful tool for creating modular web applications. The key parts of Custom Elements include:

  • constructor(): Initializes the component.
  • connectedCallback(): Handles logic when the element is added to the DOM.
  • disconnectedCallback(): Handles cleanup when the element is removed.
  • attributeChangedCallback(): Responds to changes in element attributes.

By combining custom elements with other Web Components features like the Shadow DOM and HTML templates, you can build powerful, self-contained UI components for your web applications.

Soeng Souy

Soeng Souy

Website that learns and reads, PHP, Framework Laravel, How to and download Admin template sample source code free.

Post a Comment

CAN FEEDBACK
close