Signatur
Beschreibung
Das invalid-Ereignis wird an einem HTMLInputElement ausgelöst, wenn die Constraint-Validierung ergibt, dass der Wert die Bedingungen nicht erfüllt. Solche Bedingungen sind z. B. required, pattern, min/max, minlength/maxlength, type="email" oder eine eigene Fehlermeldung über setCustomValidity(). Die Prüfung startet, wenn checkValidity() oder reportValidity() aufgerufen wird oder der Nutzer ein Formular ohne novalidate absendet.
Registrieren kannst du den Handler mit addEventListener("invalid", handler) oder über die Eigenschaft oninvalid. Das Ereignis ist ein einfaches Event. Es steigt nicht auf (bubbles: false), lässt sich aber abbrechen (cancelable: true). Mit event.preventDefault() unterdrückst du die eingebaute Fehlerblase des Browsers und kannst eigene Fehlermeldungen anzeigen.
Typische Einsatzfälle sind eigene Fehlermeldungen direkt neben dem Feld, eine einheitlich gestaltete Validierung über alle Browser hinweg und das Markieren fehlerhafter Felder mit CSS-Klassen. Weil das Ereignis nicht aufsteigt, ist die Delegation an das <form> nur in der Capture-Phase möglich (addEventListener("invalid", fn, true)).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignistyp, hier "invalid". |
|
| $handler Pflicht | (event: Event) => void | Die Rückruffunktion. Sie erhält ein Event, dessen target das ungültige Element ist. |
|
| $options | boolean | AddEventListenerOptions | false | Mit true bzw. { capture: true } fängst du das Ereignis an einem Elternelement wie <form> ab, obwohl es nicht aufsteigt. |
Rückgabewert
addEventListener gibt nichts zurück. Mit preventDefault() im Handler unterdrückst du die Standard-Fehleranzeige des Browsers.Beispiele
Eigene Fehlermeldung statt Browser-Blase
// HTML: <input id="email" type="email" required><span id="email-fehler"></span>
const email = document.querySelector('#email');
const fehler = document.querySelector('#email-fehler');
email.addEventListener('invalid', (event) => {
event.preventDefault(); // Browser-Blase unterdrücken
if (email.validity.valueMissing) {
fehler.textContent = 'Bitte gib eine E-Mail-Adresse ein.';
} else if (email.validity.typeMismatch) {
fehler.textContent = 'Das ist keine gültige E-Mail-Adresse.';
}
email.classList.add('ist-fehlerhaft');
});
email.addEventListener('input', () => {
fehler.textContent = '';
email.classList.remove('ist-fehlerhaft');
});
console.log(email.checkValidity());
Alle ungültigen Felder eines Formulars per Capture sammeln
// HTML: <form id="anmeldung"><input name="name" required><input name="alter" type="number" min="18"></form>
const form = document.querySelector('#anmeldung');
const ungueltig = [];
// Capture-Phase, da invalid nicht aufsteigt
form.addEventListener('invalid', (event) => {
ungueltig.push(event.target.name);
event.target.setAttribute('aria-invalid', 'true');
}, true);
form.elements.alter.value = '12';
form.checkValidity();
console.log(ungueltig);
oninvalid-Eigenschaft mit setCustomValidity
// HTML: <input id="plz" pattern="\\d{5}" required>
const plz = document.querySelector('#plz');
plz.oninvalid = () => {
plz.setCustomValidity('Bitte eine fünfstellige Postleitzahl eingeben.');
};
// Meldung zurücksetzen, sonst bleibt das Feld dauerhaft ungültig
plz.oninput = () => plz.setCustomValidity('');
plz.value = '123';
plz.reportValidity(); // zeigt die eigene Meldung an
console.log(plz.validationMessage);
// Handler wieder entfernen
plz.oninvalid = null;
// Wichtig · Fallstricke
- Kein Aufsteigen: Ein normaler Listener am
<form>bekommt das Ereignis nicht mit. Du brauchst die Capture-Phase (trueals drittes Argument). - Kein Ereignis bei
novalidate: Hat das Formularnovalidateoder der Absende-Buttonformnovalidate, prüft der Browser beim Absenden nicht, also wird auch keininvalidausgelöst. Rufst ducheckValidity()manuell auf, feuert es trotzdem. setCustomValidity()zurücksetzen: Eine nicht-leere Meldung macht das Feld dauerhaft ungültig. Setze sie deshalb z. B. iminput-Handler mitsetCustomValidity('')zurück.- Beim Absenden wird
invalidfür jedes ungültige Feld ausgelöst. Die Browser-Blase und der Fokus gehen aber nur an das erste Feld. Dassubmit-Ereignis bleibt aus. - Deaktivierte Felder (
disabled),readonly-Felder und Felder vom Typhiddenwerden nicht geprüft. - Serverseitige Prüfung ersetzt das nicht: Die Validierung im Browser lässt sich leicht umgehen.
- Kompatibilität: Das Ereignis wird von allen modernen Browsern unterstützt. Die Standard-Fehlerblasen sehen je nach Browser unterschiedlich aus und lassen sich nicht gestalten, daher lohnt sich oft
preventDefault()mit eigener Anzeige.