Inheriting and Extending Custom Elements

Three small Web Components demos: reuse an existing component with inheritance, enhance its prototype from another file, and expose a static API for a cleaner developer experience.

1. Base Component: Define a Toast Element

Code:
// Define the <zxx-toast> element
class ZxxToast extends HTMLElement {
    static get observedAttributes () {
        return ['open'];
    }

    get open () {
        return this.hasAttribute('open');
    }

    set open (val) {
        this.toggleAttribute('open', val);
    }

    render () {
        setTimeout(() => {
            this.hide();
        }, 3000);
    }

    show () {
        this.open = true;
    }

    hide () {
        this.open = false;
    }

    attributeChangedCallback (name, oldval, newval) {
        if (name == 'open' && this.open) {
            this.render();
        }
    }
}

if (!customElements.get('zxx-toast')) {
    customElements.define('zxx-toast', ZxxToast);
}
Result:

The element below uses the inherited open attribute plus show() and hide() methods.

This toast hides itself after 3 seconds.

2. New Component: Inherit Toast to Build Loading

Code:
// Define the <zxx-loading> element
class ZxxLoading extends ZxxToast {
    render () {
        // Display loading content
        this.innerHTML = '<i class="spin"></i>';
    }
}

if (!customElements.get('zxx-loading')) {
    customElements.define('zxx-loading', ZxxLoading);
}
Result:

<zxx-loading> overrides only render(), while keeping the base component's open, show(), and hide().

3. Prototype Extension: Add Success, Error, and Warning Methods

Code:
// Extend toast element methods
ZxxToast.prototype.success = function (content) {
    if (content) {
        this.innerHTML = content;
    }
    this.setAttribute('type', 'success');
    this.show();
};

ZxxToast.prototype.error = function (content) {
    if (content) {
        this.innerHTML = content;
    }
    this.setAttribute('type', 'error');
    this.show();
};

ZxxToast.prototype.warning = function (content) {
    if (content) {
        this.innerHTML = content;
    }
    this.setAttribute('type', 'warning');
    this.show();
};
Result:

These buttons call new methods added to ZxxToast.prototype without defining a new custom element.

Status toast

4. Static API: Create Toasts Without Writing Elements in HTML

Code:
// Extend toast element methods
ZxxToast.success = function (content) {
    const toast = new ZxxToast();

    if (content) {
        toast.innerHTML = content;
    }

    toast.setAttribute('type', 'success');
    toast.show();
    document.body.appendChild(toast);
};
Result:

Page code can call a class method directly

No <zxx-toast> element is written in this showcase. JavaScript creates and appends it.