Signatur
Beschreibung
Die Methode values() des CustomStateSet gibt ein neues Iterator-Objekt zurück. Es liefert jeden benutzerdefinierten Zustand (einen String wie "checked" oder "loading") eines Custom Elements, und zwar in der Reihenfolge, in der die Zustände mit add() hinzugefügt wurden.
Ein CustomStateSet bekommt man über ElementInternals.states, also innerhalb eines Custom Elements nach dem Aufruf von this.attachInternals(). Die Zustände darin lassen sich in CSS mit der Pseudoklasse :state(name) abfragen. Mit values() kann man den aktuellen Zustand der Komponente auslesen, etwa zum Debuggen, zum Protokollieren oder um ihn zu serialisieren.
CustomStateSet verhält sich wie ein Set. Deshalb ist values() identisch mit keys() und auch mit [Symbol.iterator](). Ein Aufruf von for...of direkt auf dem Set oder die Spread-Syntax [...states] nutzt intern denselben Iterator.
Rückgabewert
{ value: string, done: boolean } mit dem Namen eines benutzerdefinierten Zustands.Beispiele
Zustände eines Custom Elements auflisten
class ToggleButton extends HTMLElement {
#internals = this.attachInternals();
constructor() {
super();
this.#internals.states.add('ready');
this.addEventListener('click', () => this.toggle());
}
toggle() {
const { states } = this.#internals;
states.has('on') ? states.delete('on') : states.add('on');
}
get currentStates() {
return [...this.#internals.states.values()];
}
}
customElements.define('toggle-button', ToggleButton);
const btn = document.createElement('toggle-button');
document.body.append(btn);
btn.toggle();
console.log(btn.currentStates);
Iterator schrittweise mit next() durchlaufen
class StatusBox extends HTMLElement {
internals = this.attachInternals();
}
customElements.define('status-box', StatusBox);
const box = new StatusBox();
box.internals.states.add('loading');
box.internals.states.add('error');
const it = box.internals.states.values();
console.log(it.next()); // erster Zustand
console.log(it.next()); // zweiter Zustand
console.log(it.next()); // Ende erreicht
Zustände für Debug-Ausgabe als Attribut spiegeln
class FormField extends HTMLElement {
#internals = this.attachInternals();
setState(name, active) {
const { states } = this.#internals;
active ? states.add(name) : states.delete(name);
// Für DevTools sichtbar machen
this.dataset.states = Array.from(states.values()).join(' ');
}
}
customElements.define('form-field', FormField);
const field = document.createElement('form-field');
field.setState('invalid', true);
field.setState('touched', true);
console.log(field.dataset.states);
// Wichtig · Fallstricke
- Live-Iterator: Der Iterator ist keine Momentaufnahme. Zustände, die während des Durchlaufens hinzugefügt oder entfernt werden, wirken sich auf die restliche Iteration aus. Wer eine feste Kopie braucht, sollte vorher
[...states.values()]erzeugen. - Nur intern erreichbar: Das
CustomStateSethängt amElementInternals-Objekt. Speichert maninternalsprivat (#internals), kann Code von außen die Zustände nicht auslesen. Das ist so gewollt und schützt die Kapselung. - Kompatibilität: Die heutige Form mit Zustandsnamen ohne Präfix und der CSS-Pseudoklasse
:state(name)gibt es erst seit Chrome 125, Firefox 126 und Safari 17.4. Ältere Chromium-Versionen (90–124) haben die veraltete Schreibweise--namemit dem Selektor:--nameverwendet. Für ältere Browser sollte man die Unterstützung prüfen, z. B. mitCSS.supports('selector(:state(x))'). values(),keys()und[Symbol.iterator]()liefern dasselbe Ergebnis.entries()liefert dagegen Paare der Form[wert, wert].