Verwenden Sie kein ausgeblendetes <input>, um den Wert eines benutzerdefinierten Steuerelements in einem Formular anzuzeigen. Verwenden Sie Form-Associated Custom Elements (FACE): Mit formAssociated und ElementInternals sendet das Element seinen eigenen Wert, nimmt an der Validierung teil und spiegelt den Formularstatus nativ wider.
class RatingInput extends HTMLElement {
// MANDATORY: opt in. Without this, attachInternals() form APIs are unavailable.
static formAssociated = true;
#internals;
#value = '';
constructor() {
super();
this.#internals = this.attachInternals();
this.attachShadow({ mode: 'open', delegatesFocus: true });
}
connectedCallback() {
// Validate initial state once attributes (such as `required`) are present.
this.#validate();
}
get value() { return this.#value; }
set value(v) {
this.#value = v;
// Push the value into the owning <form> for submission.
this.#internals.setFormValue(v);
this.#validate();
}
#validate() {
if (this.hasAttribute('required') && !this.#value) {
// Mark invalid and supply the native validation message + anchor.
this.#internals.setValidity(
{ valueMissing: true },
'Please choose a rating.',
this.shadowRoot.querySelector('[tabindex]'),
);
} else {
this.#internals.setValidity({}); // clear
}
}
// Optional FACE lifecycle hooks:
formResetCallback() { this.value = ''; }
formDisabledCallback(disabled) {
// Disable internal controls so they leave the tab order and ignore clicks.
// Do NOT toggle `disabled` on `this`, or a `<fieldset disabled>` toggle will
// leave the host permanently stuck with its own `disabled` attribute.
for (const el of this.shadowRoot.querySelectorAll('button')) {
el.disabled = disabled;
}
}
formStateRestoreCallback(state) { this.value = state; }
}
customElements.define('rating-input', RatingInput);
Wichtige Punkte:
static formAssociated = trueist ERFORDERLICH. Dadurch werden die formularbezogenenElementInternals-Methoden und derformXxxCallback-Lebenszyklus freigeschaltet.setFormValue(value)wird gesendet, ohne dass eine ausgeblendete Eingabe erforderlich ist. Übergeben Sie einFormDatafür Steuerelemente mit mehreren Werten.setValidity(flags, message, anchor)lässt sich in die native Einschränkungsvalidierung einbinden: Das Formular wird nicht gesendet, wenn es ungültig ist,:invalid/:validgelten und das Ankerelement wird beim Melden fokussiert. RufesetValidity({})auf, um die Daten zu löschen. Die interaktionssensitiven Pseudoklassen:user-valid/:user-invalidsind in den verschiedenen Browsern nicht einheitlich mit formularbezogenen Elementen verknüpft. Prüfen Sie die Unterstützung, bevor Sie sich darauf verlassen, anstatt davon auszugehen, dass sie die Nutzerinteraktion wie bei nativen Steuerelementen erfassen.- Implementieren Sie
formResetCallback,formDisabledCallbackundformStateRestoreCallback, damit sich das Element beim Zurücksetzen,fieldset[disabled]und beim Wiederherstellen des automatischen Ausfüllens beim Vor- und Zurückgehen wie ein natives Steuerelement verhält. Deaktivieren Sie informDisabledCallback(disabled)interne Steuerelemente (oder entfernen Sie sie aus der Tab-Reihenfolge und ignorieren Sie Eingaben), anstattdisabledauf dem Host festzulegen. Wenn Sie das Host-Attribut im Callback festlegen, wird die erneute Aktivierung verhindert, wenn ein übergeordnetes<fieldset>-Element wieder aktiviert wird, und der Host entspricht bereits automatisch:disabled. - Folgen Sie den Plattformkonventionen für gesendete Ereignisse und bevorzugen Sie die integrierten Ereignisse
inputundchangegegenüber benutzerdefinierten Ereignissen.inputwird ausgelöst, wenn sich der Wert als direkte Folge einer Nutzeraktion ändert (Eingabe, Ziehen eines Schiebereglers).changewird einmal pro Änderungsstream ausgelöst, wenn der Nutzer die Änderung bestätigt (Loslassen des Schiebereglers, Verlassen des Felds). Erstellen Sie sie mitInputEventbzw.Event.
Fallback-Strategien
Prüfen Sie die Unterstützung von static formAssociated, bevor Sie sich darauf verlassen: 'attachInternals' in HTMLElement.prototype && 'setFormValue' in ElementInternals.prototype. Wenn es nicht verfügbar ist, greifen Sie auf ein visuell ausgeblendetes natives <input>-Element zurück, das mit dem Wert des Steuerelements synchronisiert ist, damit das Formular trotzdem gesendet wird. Dies ist der einzige Fall, in dem das Muster für ausgeblendete Eingaben gerechtfertigt ist.