A stateful Web Component with event handling
Try clicking the buttons below. The counter maintains its own state!
class CounterWidget extends HTMLElement {
constructor() {
super();
this._count = 0;
}
connectedCallback() {
// Get initial value from attribute
this._count = parseInt(this.getAttribute('initial')) || 0;
this.render();
this.attachEventListeners();
}
increment() {
this._count++;
this.render();
// Dispatch custom event
this.dispatchEvent(new CustomEvent('countchange', {
detail: { count: this._count }
}));
}
decrement() {
this._count--;
this.render();
this.dispatchEvent(new CustomEvent('countchange', {
detail: { count: this._count }
}));
}
reset() {
this._count = 0;
this.render();
}
render() {
this.innerHTML = \`
<div style="display: flex; align-items: center; gap: 10px;
padding: 20px; background: #f5f0e8; border-radius: 0;
margin: 10px 0;">
<button data-action="decrement" style="
padding: 10px 20px; border: none; background: #2d1b69;
color: white; border-radius: 0; cursor: pointer;
font-size: 18px; font-weight: bold;">
-
</button>
<span style="font-size: 32px; font-weight: bold;
color: #2d1b69; min-width: 60px; text-align: center;">
\${this._count}
</span>
<button data-action="increment" style="
padding: 10px 20px; border: none; background: #2d1b69;
color: white; border-radius: 0; cursor: pointer;
font-size: 18px; font-weight: bold;">
+
</button>
<button data-action="reset" style="
padding: 10px 20px; border: none; background: #e8e3db;
color: #1a1a1a; border-radius: 0; cursor: pointer;">
Reset
</button>
</div>
\`;
// Re-attach event listeners after render
this.attachEventListeners();
}
attachEventListeners() {
const buttons = this.querySelectorAll('button');
buttons.forEach(button => {
button.addEventListener('click', (e) => {
const action = e.target.getAttribute('data-action');
if (action === 'increment') this.increment();
if (action === 'decrement') this.decrement();
if (action === 'reset') this.reset();
});
});
}
}
customElements.define('counter-widget', CounterWidget);
_count statecountchange events for parent componentsinitial attribute for starting valueOpen the console to see events. Try this code:
document.querySelector('counter-widget').addEventListener('countchange', (e) => {
console.log('Count changed to:', e.detail.count);
});