Signatur
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
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>
`;
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);
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 auflabelseinenDOMExceptionvom TypNotSupportedError. labelsist nur über dasElementInternals-Objekt erreichbar, nicht automatisch über das Element selbst. Werelement.labelswie bei nativen Eingabefeldern anbieten will, muss einen eigenen Getter definieren. Dasinternals-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
NodeListist 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).