Start · Sprachen · JavaScript · Referenz · CustomStateSet.add()

CustomStateSet.add()

Methode

Fügt einem <code>CustomStateSet</code> einen benutzerdefinierten Zustand hinzu, den man per CSS mit der Pseudoklasse <code>:state()</code> abfragen kann.

seit JavaScript Baseline 2024: Chrome 125, Edge 125, Firefox 126, Kategorie: webapi

Signatur

CustomStateSet.prototype.add(value)

Beschreibung

Mit add() setzt ein autonomes Custom Element einen eigenen Zustand, zum Beispiel "checked", "loading" oder "invalid". Das CustomStateSet erreicht man über ElementInternals.states. Die Instanz dazu liefert this.attachInternals() im Konstruktor des Elements.

Ist ein Zustand gesetzt, passt die CSS-Pseudoklasse :state(name) auf das Element, von außen etwa mit my-toggle:state(checked) und im Shadow DOM mit :host(:state(checked)). Anders als Attribute oder Klassen sind diese Zustände intern: Nutzer des Elements können sie nicht von außen setzen oder überschreiben. Die Komponente kontrolliert ihren Zustand also selbst und gibt ihn trotzdem zum Gestalten frei, ähnlich wie bei eingebauten Pseudoklassen wie :checked.

CustomStateSet verhält sich wie ein Set. Ist der Wert schon enthalten, ändert add() nichts. Zum Entfernen dient delete(), zum Prüfen has(). Zwischen den Zuständen umschalten kann man also mit add()/delete().

Parameter

Name Typ Default Beschreibung
$value Pflicht string Name des benutzerdefinierten Zustands, z. B. "checked". Er wird in CSS als :state(checked) abgefragt. Andere Werte werden in einen String umgewandelt.

Rückgabewert

Typ
CustomStateSet
Beschreibung
Nach der WebIDL-Semantik für mengenartige Objekte (setlike) gibt die Methode das CustomStateSet selbst zurück. MDN gibt teils undefined an, deshalb sollte man sich nicht auf Verkettung verlassen.

Beispiele

Umschaltbares Element mit Zustand „checked“

class MyToggle extends HTMLElement {
  #internals;

  constructor() {
    super();
    this.#internals = this.attachInternals();
    this.addEventListener('click', () => this.toggle());
  }

  get checked() {
    return this.#internals.states.has('checked');
  }

  toggle() {
    if (this.checked) {
      this.#internals.states.delete('checked');
    } else {
      this.#internals.states.add('checked');
    }
    console.log('checked:', this.checked);
  }
}

customElements.define('my-toggle', MyToggle);

const toggle = document.createElement('my-toggle');
toggle.textContent = 'Schalter';
document.body.append(toggle);
toggle.click();
checked: true

Zustand per CSS gestalten

const style = document.createElement('style');
style.textContent = `
  my-toggle { padding: 4px 8px; border: 1px solid #888; cursor: pointer; }
  my-toggle:state(checked) { background: seagreen; color: white; }
`;
document.head.append(style);

// Nach toggle.click() aus Beispiel 1 ist das Element grün hinterlegt
console.log(document.querySelector('my-toggle')?.matches(':state(checked)'));
true

Ladezustand bei asynchroner Arbeit

class DataView extends HTMLElement {
  #internals = this.attachInternals();

  async load(url) {
    this.#internals.states.add('loading');
    try {
      const res = await fetch(url);
      this.textContent = (await res.json()).title;
      this.#internals.states.delete('error');
    } catch {
      this.#internals.states.add('error');
    } finally {
      this.#internals.states.delete('loading');
    }
  }
}

customElements.define('data-view', DataView);

const view = document.createElement('data-view');
document.body.append(view);
view.load('https://jsonplaceholder.typicode.com/todos/1');
console.log(view.matches(':state(loading)'));
true

// Wichtig · Fallstricke

  • Nur für autonome Custom Elements: attachInternals() funktioniert nicht bei eingebauten Elementen und nicht bei angepassten eingebauten Elementen (extends: 'button'). In diesen Fällen wird ein NotSupportedError geworfen.
  • Alte Chromium-Syntax: Chrome/Edge 90–124 unterstützten nur Namen mit doppeltem Bindestrich (add('--checked')) und das CSS :--checked. Namen ohne Bindestriche lösten dort einen SyntaxError aus. Falls alte Versionen unterstützt werden müssen, den Aufruf in try { states.add('checked') } catch { states.add('--checked') } einpacken und beide Selektoren im CSS angeben.
  • Browserunterstützung: Seit 2024 in allen aktuellen Browsern verfügbar (Chrome 125, Firefox 126, Safari 17.4). Unterstützung prüfen mit 'CustomStateSet' in window.
  • Zustände ersetzen keine ARIA-Attribute. Für Barrierefreiheit zusätzlich z. B. internals.ariaChecked setzen.
  • Ist der Wert schon enthalten, passiert nichts. Es gibt keinen Fehler und kein Duplikat.