Skip to content

Slot Change Events — Complete Guide

DodaTech Updated 2026-06-28 2 min read

In this tutorial, you will learn about Slot Change Events. We cover key concepts, practical examples, and best practices to help you master this topic.

Slotchange events fire when slot content changes, enabling components to react dynamically to content additions, removals, or reconfiguration.

What You'll Learn

  • How to listen for slotchange events
  • When slotchange fires and when it does not
  • How to access assigned nodes
  • How to use slotchange for dynamic layouts

Why It Matters

Components often need to know when their slotted content changes. A tabs component needs to recount panels. A list component needs to update item count.

flowchart LR
  A[Slot Content Changes] --> B[slotchange Event]
  B --> C[assignedNodes]
  B --> D[assignedElements]
  C --> E[Process new nodes]
  D --> F[Update counts/layout]

Basic Slotchange

class SlotCounter extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
            <style>
                .counter { font-size: 0.9em; color: #666; margin-bottom: 8px; }
                .list { border: 1px solid #ddd; border-radius: 4px; padding: 8px; }
            </style>
            <div class="counter">Items: <span id="count">0</span></div>
            <div class="list"><slot id="slot"></slot></div>
        `;

        const slot = this.shadowRoot.getElementById('slot');
        slot.addEventListener('slotchange', (e) => {
            const nodes = slot.assignedNodes();
            const elements = slot.assignedElements();
            const count = elements.length;
            console.log('Slot changed:', count, 'elements');
            this.shadowRoot.getElementById('count').textContent = count;
        });
    }
}
customElements.define('slot-counter', SlotCounter);

Advanced Slot Tracking

class DynamicTabs extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
            <style>
                .tab-bar { display: flex; gap: 4px; margin-bottom: 8px; }
                .tab { padding: 8px 16px; cursor: pointer; border: 1px solid #ddd; border-radius: 4px 4px 0 0; }
                .tab.active { background: #3498db; color: white; border-color: #3498db; }
                .panels { border: 1px solid #ddd; padding: 16px; border-radius: 0 4px 4px 4px; }
                .panel { display: none; }
                .panel.active { display: block; }
            </style>
            <div class="tab-bar" id="tabBar"></div>
            <div class="panels"><slot id="panelSlot"></slot></div>
        `;

        const slot = this.shadowRoot.getElementById('panelSlot');
        slot.addEventListener('slotchange', () => this._rebuildTabs());
    }

    _rebuildTabs() {
        const panels = this.shadowRoot.getElementById('panelSlot').assignedElements();
        const tabBar = this.shadowRoot.getElementById('tabBar');
        tabBar.innerHTML = '';

        panels.forEach((panel, index) => {
            const tab = document.createElement('button');
            tab.className = 'tab' + (index === 0 ? ' active' : '');
            tab.textContent = panel.getAttribute('title') || 'Tab ' + (index + 1);
            tab.addEventListener('click', () => this._selectTab(index));
            tabBar.appendChild(tab);

            panel.classList.toggle('active', index === 0);
        });
    }

    _selectTab(index) {
        const tabs = this.shadowRoot.querySelectorAll('.tab');
        const panels = this.shadowRoot.getElementById('panelSlot').assignedElements();
        tabs.forEach((t, i) => t.classList.toggle('active', i === index));
        panels.forEach((p, i) => p.classList.toggle('active', i === index));
    }
}
customElements.define('dynamic-tabs', DynamicTabs);

Common Mistakes

  1. Expecting slotchange to fire on initial assignment (it does not)
  2. Processing slotchange before the element is connected
  3. Not using assignedElements() when only HTMLElements are needed

Practice Questions

  1. When does slotchange fire? When the assigned nodes change, not on initial assignment.
  2. How do you get only element nodes from a slot? Use slot.assignedElements().

Mini Project

Build a todo list component that tracks its item count via slotchange. Show a message when the list is empty. Allow adding and removing items dynamically.

What's Next

Lesson 11: Event Retargeting

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro