Build Reusable UI with Web Components: A Step‑by‑Step Counter Example
Learn how to create reusable, encapsulated UI components using Web Components by building a simple counter element with Custom Elements, Templates, Shadow DOM, properties, events, and attributes, and see how to integrate it into any framework, handle data binding, and dispatch custom events.
Custom Elements
Custom Elements API allows defining new HTML tags by extending HTMLElement. A minimal custom element can be created with a class that defines a constructor and connectedCallback, then registered with customElements.define.
class XCounter extends HTMLElement {
constructor() {
super();
this._value = 0;
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `
<style>button, p {display:inline-block;}</style>
<button aria-label="decrement">-</button>
<p>0</p>
<button aria-label="increment">+</button>`;
this._setup();
}
_setup() {
this._valueElement = this.shadowRoot.querySelector('p');
this._incBtn = this.shadowRoot.querySelectorAll('button')[1];
this._decBtn = this.shadowRoot.querySelectorAll('button')[0];
this._incBtn.addEventListener('click', () => this.value++);
this._decBtn.addEventListener('click', () => this.value--);
}
set value(v) {
this._value = v;
this._valueElement.innerText = v;
this.dispatchEvent(new CustomEvent('valueChange', {detail: v}));
}
get value() { return this._value; }
static get observedAttributes() { return ['value']; }
attributeChangedCallback(name, oldVal, newVal) {
if (name === 'value') this.value = parseInt(newVal, 10);
}
}
customElements.define('x-counter', XCounter);Properties
The component exposes a public value property with getter and setter. Changing the property updates the displayed number and fires a valueChange custom event.
Events
Consumers can listen for the valueChange event to react when the counter changes.
const counter = document.querySelector('x-counter');
counter.addEventListener('valueChange', e => console.log('new value:', e.detail));
counter.value = 10;Attributes
Initial values can be passed via the value attribute. The attribute is observed and synchronized with the property.
<x-counter value="5"></x-counter>Summary
Web Components provide a standards‑based way to build reusable UI widgets that work across frameworks. By combining Custom Elements, Templates, and Shadow DOM you get encapsulation, style isolation, and a clean API for properties, events, and attributes.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
