Start · Sprachen · JavaScript · Referenz · ElementInternals.labels

ElementInternals.labels

Eigenschaft

Gibt als schreibgeschützte <code>NodeList</code> alle <code>&lt;label&gt;</code>-Elemente zurück, die einem formularassoziierten Custom Element zugeordnet sind.

seit JavaScript Baseline 2023: Chrome 77+, Firefox 93+, Safari 16. Kategorie: webapi

Signatur

ElementInternals.labels

Beschreibung

Die schreibgeschützte Eigenschaft labels der Schnittstelle ElementInternals liefert eine NodeList mit allen <label>-Elementen, die mit dem Host-Element verknüpft sind. Das Custom Element verhält sich damit wie ein natives Formularelement, etwa <input>, das eine ähnliche Eigenschaft HTMLInputElement.labels hat.

Ein Label ist zugeordnet, wenn es das Element umschließt oder über das Attribut for auf die id des Custom Elements verweist. Voraussetzung ist, dass die Klasse des Custom Elements als formularassoziiert gekennzeichnet ist (static formAssociated = true) und this.attachInternals() aufgerufen wurde.

Typische Einsatzfälle: den Label-Text auslesen, etwa für Barrierefreiheit, Tooltips oder Fehlermeldungen, Klicks auf Labels abfangen oder prüfen, ob eine Komponente überhaupt beschriftet ist. Die Liste ist live, sie spiegelt also Änderungen im DOM automatisch wider.

Rückgabewert

Typ
NodeList
Beschreibung
Eine live NodeList der zugeordneten <label>-Elemente. Gibt es keine Labels, ist die Liste leer.

Beispiele

Formularassoziiertes Element anlegen und Labels auslesen

class RatingInput extends HTMLElement {
  static formAssociated = true;

  constructor() {
    super();
    this.internals = this.attachInternals();
  }

  connectedCallback() {
    const texte = [...this.internals.labels].map((l) => l.textContent.trim());
    console.log('Labels:', texte);
  }
}

customElements.define('rating-input', RatingInput);

document.body.innerHTML = `
  <label for="bewertung">Ihre Bewertung</label>
  <rating-input id="bewertung"></rating-input>
`;
Labels: ["Ihre Bewertung"]

Umschließendes Label und for-Label kombiniert

class MyField extends HTMLElement {
  static formAssociated = true;
  #internals = this.attachInternals();
  get labels() {
    return this.#internals.labels;
  }
}
customElements.define('my-field', MyField);

document.body.innerHTML = `
  <label>Name <my-field id="name"></my-field></label>
  <label for="name">(Pflichtfeld)</label>
`;

const feld = document.querySelector('my-field');
console.log(feld.labels.length);
2

Klick auf Label: Fokus setzen und fehlende Beschriftung melden

class ColorPicker extends HTMLElement {
  static formAssociated = true;

  constructor() {
    super();
    this.internals = this.attachInternals();
    this.tabIndex = 0;
  }

  connectedCallback() {
    const { labels } = this.internals;
    if (labels.length === 0) {
      console.warn('color-picker ohne Label – bitte aria-label setzen');
      return;
    }
    labels.forEach((label) =>
      label.addEventListener('click', () => this.focus())
    );
  }
}

customElements.define('color-picker', ColorPicker);

// Wichtig · Fallstricke

  • Ist das Custom Element nicht formularassoziiert (kein static formAssociated = true), wirft der Zugriff auf labels einen DOMException vom Typ NotSupportedError.
  • labels ist nur über das ElementInternals-Objekt erreichbar, nicht automatisch über das Element selbst. Wer element.labels wie bei nativen Eingabefeldern anbieten will, muss einen eigenen Getter definieren. Das internals-Objekt sollte möglichst privat bleiben (#internals).
  • Labels innerhalb des Shadow DOM der Komponente zählen nicht. Es werden nur Labels im selben Baum wie der Host berücksichtigt.
  • Die NodeList ist live. Wer sie durchläuft und dabei das DOM verändert, sollte sie vorher mit [...labels] kopieren.
  • Kompatibilität: Chrome/Edge seit Version 77, Firefox seit 93, Safari erst seit 16.4. Für ältere Safari-Versionen gibt es ein Polyfill (element-internals-polyfill).