Signatur
Beschreibung
Die schreibgeschützte Eigenschaft form des ElementInternals-Interfaces liefert das Formular, zu dem ein formularassoziiertes Custom Element gehört. Sie entspricht der Eigenschaft form nativer Formularelemente wie <input> oder <select>.
Damit die Eigenschaft funktioniert, muss die Custom-Element-Klasse static formAssociated = true deklarieren und im Konstruktor per this.attachInternals() ein ElementInternals-Objekt erhalten. Die Zuordnung zum Formular bestimmt der Browser: Entweder ist das Element ein Nachfahre eines <form>, oder es verweist über das Attribut form="formular-id" auf ein Formular an anderer Stelle im Dokument.
Typische Einsatzfälle sind: auf das submit- oder reset-Ereignis des Formulars hören, das Formular aus der Komponente heraus absenden (z. B. bei Enter-Taste mit requestSubmit()) oder andere Felder desselben Formulars auslesen. Ändert sich die Zuordnung, ruft der Browser den Lifecycle-Callback formAssociatedCallback(form) auf. Dort lässt sich der neue Wert direkt verarbeiten.
Rückgabewert
HTMLFormElement oder null, wenn das Element keinem Formular zugeordnet ist.Beispiele
Formularassoziiertes Custom Element und Zugriff auf form
class RatingInput extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals = this.attachInternals();
}
connectedCallback() {
console.log('Zugeordnetes Formular:', this.internals.form?.id ?? null);
}
}
customElements.define('rating-input', RatingInput);
document.body.innerHTML = `
<form id="feedback">
<rating-input name="sterne"></rating-input>
</form>
<rating-input></rating-input>
`;
Formular per Enter-Taste aus der Komponente absenden
class SearchField extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals = this.attachInternals();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = '<input type="search">';
const input = shadow.querySelector('input');
input.addEventListener('input', () => {
this.internals.setFormValue(input.value);
});
input.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
// requestSubmit() löst Validierung und submit-Ereignis aus
this.internals.form?.requestSubmit();
}
});
}
}
customElements.define('search-field', SearchField);
Auf Zuordnungswechsel reagieren (form-Attribut)
class TagPicker extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals = this.attachInternals();
}
// Wird aufgerufen, wenn sich die Formularzuordnung ändert
formAssociatedCallback(form) {
console.log('Neues Formular:', form?.id ?? null);
console.log('Identisch mit internals.form:', form === this.internals.form);
}
}
customElements.define('tag-picker', TagPicker);
document.body.innerHTML = `
<form id="artikel"></form>
<tag-picker form="artikel"></tag-picker>
`;
// Wichtig · Fallstricke
- Fehlt
static formAssociated = truein der Klasse, wirft schon der Zugriff aufinternals.formeineNotSupportedError-DOMException. Außerdem erscheinen die Werte der Komponente dann nicht inFormData. - Die Eigenschaft ist schreibgeschützt. Die Zuordnung ändert man über die DOM-Position oder das Attribut
form, nicht durch eine Zuweisung. - Im Konstruktor ist das Element meist noch nicht im DOM,
formist dort also in der Regelnull. Auswerten sollte man den Wert erst inconnectedCallbackoderformAssociatedCallback. - Ein Custom Element im Shadow DOM einer anderen Komponente wird keinem
<form>im Light DOM zugeordnet. Die Formularzuordnung wirkt nicht über Shadow-Grenzen hinweg. - Bei Ereignis-Listenern, die man über
internals.formregistriert, vorsichtig sein: Ändert sich die Zuordnung, sollte man sie informAssociatedCallbackbzw.disconnectedCallbackwieder entfernen, sonst entstehen Speicherlecks. - Kompatibilität: Chrome/Edge 77+, Firefox 98+, Safari erst ab 16.4. Für ältere Safari-Versionen gibt es das Polyfill
element-internals-polyfill.