Signatur
Beschreibung
Das Ereignis slotchange gehört zu HTMLSlotElement. Es wird ausgelöst, wenn sich die Menge der zugewiesenen Knoten eines Slots ändert. Das passiert etwa, wenn ein Kind-Element mit passendem slot-Attribut in den Host eingefügt oder entfernt wird, wenn sich das slot-Attribut eines Kindes ändert oder wenn bei manueller Slot-Zuweisung slot.assign() aufgerufen wird.
Web Components nutzen das Ereignis, um auf Inhalte zu reagieren, die ein Nutzer der Komponente hineinreicht. Typische Fälle sind Tab-Leisten, die ihre Tabs aus den übergebenen Kindern erzeugen, Listen, die Einträge zählen, oder Komponenten, die geslottete Elemente mit ARIA-Attributen versehen. Die aktuellen Knoten liest man im Handler mit slot.assignedNodes() oder slot.assignedElements() aus.
Das Ereignis bubbelt (bubbles: true), ist aber nicht composed. Es verlässt also den Shadow-Tree nicht. Deshalb kann man es auch zentral am shadowRoot abfangen und über event.target herausfinden, welcher Slot betroffen ist. Es ist nicht abbrechbar und hat den Typ Event. Statt addEventListener kann man auch die Eigenschaft slot.onslotchange setzen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "slotchange". |
|
| $handler Pflicht | (event: Event) => void | Callback, der ein normales Event erhält. event.target ist der betroffene HTMLSlotElement. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, signal oder capture. |
Rückgabewert
addEventListener gibt nichts zurück.Beispiele
Geslottete Elemente zählen
class ItemList extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
root.innerHTML = `<p>Einträge: <span id="count">0</span></p><slot></slot>`;
const slot = root.querySelector('slot');
const count = root.getElementById('count');
slot.addEventListener('slotchange', () => {
const items = slot.assignedElements();
count.textContent = items.length;
console.log('Einträge:', items.length);
});
}
}
customElements.define('item-list', ItemList);
const list = document.createElement('item-list');
list.innerHTML = '<li>A</li><li>B</li>';
document.body.append(list);
// Später einen Eintrag ergänzen
setTimeout(() => list.append(Object.assign(document.createElement('li'), { textContent: 'C' })), 500);
Zentral am shadowRoot abfangen (benannte Slots)
class CardBox extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
root.innerHTML = `
<header><slot name="title"></slot></header>
<main><slot></slot></main>`;
// slotchange bubbelt innerhalb des Shadow-Trees
root.addEventListener('slotchange', (event) => {
const slot = event.target;
console.log(`Slot "${slot.name || 'default'}" hat jetzt ${slot.assignedNodes().length} Knoten`);
});
}
}
customElements.define('card-box', CardBox);
const card = document.createElement('card-box');
card.innerHTML = '<h2 slot="title">Hallo</h2><p>Inhalt</p>';
document.body.append(card);
on-Property verwenden und Listener wieder entfernen
const host = document.createElement('div');
const root = host.attachShadow({ mode: 'open' });
const slot = document.createElement('slot');
root.append(slot);
document.body.append(host);
// Variante 1: on-Property
slot.onslotchange = () => console.log('onslotchange:', slot.assignedNodes().length);
// Variante 2: addEventListener mit anschließendem Entfernen
const handler = () => console.log('Listener aktiv');
slot.addEventListener('slotchange', handler);
host.append(document.createElement('span'));
setTimeout(() => {
slot.removeEventListener('slotchange', handler);
slot.onslotchange = null;
host.append(document.createElement('span')); // keine Ausgabe mehr
}, 100);
// Wichtig · Fallstricke
- Nur direkte Kinder zählen: Ändert sich etwas innerhalb eines geslotteten Elements (z. B. Text oder Enkel-Elemente), wird kein
slotchangeausgelöst. Für solche Änderungen braucht man einenMutationObserver. - Asynchron und gebündelt: Das Ereignis wird als Microtask ausgelöst, so ähnlich wie bei Mutation Observern. Mehrere Änderungen direkt hintereinander ergeben meist nur ein Ereignis.
- Erste Zuweisung: Ob der Slot beim Upgrade schon vorhandener Light-DOM-Kinder ein Ereignis bekommt, hängt davon ab, ob der Listener vor der Zuweisung registriert war. Man sollte daher zusätzlich einmal direkt
assignedElements()auslesen, zum Beispiel inconnectedCallback. - Nicht composed: Außerhalb des Shadow-Roots, etwa am Host oder an
document, kommt das Ereignis nicht an. - Verschachtelte Slots: Mit
assignedNodes({ flatten: true })werden auch weitergereichte Slot-Inhalte aufgelöst. - Kompatibilität: Chrome 53+, Firefox 63+, Safari 10.1+, Edge 79+. Die IDL-Eigenschaft
onslotchangegibt es in älteren Versionen teilweise erst später, deshalb istaddEventListenerdie sicherere Wahl.