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

CustomStateSet.has()

Methode

Prüft, ob ein benutzerdefiniertes Element gerade einen bestimmten Custom State (z. B. <code>"checked"</code>) in seinem <code>CustomStateSet</code> hat, und gibt <code>true</code> oder <code>false</code> zurück.

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

Signatur

CustomStateSet.prototype.has(value)

Beschreibung

Die Methode has() des Interfaces CustomStateSet gibt einen booleschen Wert zurück. Er zeigt an, ob der übergebene String als Custom State im Set steht. Ein CustomStateSet bekommst du über ElementInternals.states. Das geht nur in einem autonomen benutzerdefinierten Element, das this.attachInternals() aufgerufen hat.

Mit Custom States machen Web Components eigene Zustände nach außen sichtbar, ähnlich wie eingebaute Pseudoklassen wie :checked oder :disabled. Jeden Wert im Set kannst du in CSS mit der Pseudoklasse :state(name) ansprechen. Mit has() fragst du diesen Zustand im JavaScript-Code der Komponente ab. Das brauchst du zum Beispiel, um einen Zustand umzuschalten, um Ereignisse davon abhängig auszulösen oder um Getter wie get checked() umzusetzen.

CustomStateSet verhält sich wie ein Set, das nur Strings enthält. has() vergleicht deshalb exakt und unterscheidet Groß- und Kleinschreibung. Der Aufruf ändert nichts am Element und löst keine Neuberechnung der Stile aus.

Parameter

Name Typ Default Beschreibung
$value Pflicht string Name des gesuchten Custom States, z. B. "checked". Werte, die keine Strings sind, werden nach WebIDL-Regeln in einen String umgewandelt.

Beispiele

Zustand in einer Checkbox-Komponente umschalten

class MyCheckbox extends HTMLElement {
  #internals;

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

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

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

customElements.define('my-checkbox', MyCheckbox);

const box = document.createElement('my-checkbox');
document.body.append(box);
box.click();
box.click();
checked: true checked: false

Groß- und Kleinschreibung beachten

class StatusBadge extends HTMLElement {
  constructor() {
    super();
    this.internals = this.attachInternals();
    this.internals.states.add('loading');
  }
}
customElements.define('status-badge', StatusBadge);

const badge = new StatusBadge();
const { states } = badge.internals;
console.log(states.has('loading'));
console.log(states.has('Loading'));
console.log(states.has('ready'));
true false false

Nur bei echter Zustandsänderung ein Event auslösen

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

  setOn(on) {
    const { states } = this.#internals;
    if (states.has('on') === on) return; // keine Änderung
    on ? states.add('on') : states.delete('on');
    this.dispatchEvent(new CustomEvent('change', { detail: { on } }));
  }
}
customElements.define('toggle-switch', ToggleSwitch);

const sw = document.createElement('toggle-switch');
sw.addEventListener('change', (e) => console.log('change:', e.detail.on));
sw.setOn(true);
sw.setOn(true); // löst nichts aus
sw.setOn(false);

/* CSS dazu:
   toggle-switch:state(on) { background: green; }
*/
change: true change: false

// Wichtig · Fallstricke

  • Nur für autonome Custom Elements: attachInternals() wirft bei eingebauten Elementen und bei angepassten eingebauten Elementen (is="…") einen NotSupportedError. Außerhalb der Komponente kommst du nur an das Set, wenn die Komponente ElementInternals bewusst nach außen gibt. Üblicherweise hält man es in einem privaten Feld.
  • Alte Syntax: Chrome/Edge 90–124 kannten nur die Form mit Präfix --name und die CSS-Syntax :--name. Werte ohne -- haben dort bei add() einen Fehler ausgelöst. states.has('--checked') und states.has('checked') sind verschiedene Werte. Wenn du ältere Browser unterstützen willst, musst du beide Varianten berücksichtigen.
  • Feature-Erkennung: Zum Beispiel mit 'states' in ElementInternals.prototype oder in CSS mit CSS.supports('selector(:state(x))').
  • Die Custom States sind nicht mit Attributen verknüpft. Sie erscheinen nicht im DOM und werden auch nicht serialisiert (outerHTML). Wenn der Zustand von außen gesetzt werden soll, synchronisiere ihn selbst mit einem Attribut oder einer Eigenschaft.
  • has() hat die Laufzeit einer normalen Set-Abfrage und kostet praktisch nichts. Es löst keine Neuberechnung der Stile aus.