HTML-Formularvalidierung und die Constraint Validation API verwenden
Das Erstellen von Webformularen war schon immer eine komplexe Aufgabe. Das Formular selbst mit Markup zu versehen ist einfach. Schwieriger ist es, zu prüfen, ob jedes Feld einen gültigen und stimmigen Wert enthält. Auch die Nutzer über ein Problem zu informieren, kann aufwendig sein. HTML5 führte neue Mechanismen für Formulare ein: neue semantische Typen für das Element <input> und die Constraint Validation, die die Prüfung von Formularinhalten auf der Client-Seite erleichtert. Grundlegende, gängige Bedingungen lassen sich ohne JavaScript prüfen, indem neue Attribute gesetzt werden. Komplexere Bedingungen können mit der Constraint Validation API geprüft werden.
Eine grundlegende Einführung in diese Konzepte mit Beispielen finden Sie im Tutorial zur Formularvalidierung.
Hinweis: Die HTML-Constraint-Validation macht eine Validierung auf der Server-Seite nicht überflüssig. Auch wenn mit deutlich weniger ungültigen Formularanfragen zu rechnen ist, können solche Anfragen weiterhin auf verschiedene Weise gesendet werden:
- Durch Ändern des HTML mit den Entwicklertools des Browsers.
- Durch manuelles Erstellen einer HTTP-Anfrage ohne Verwendung des Formulars.
- Durch programmgesteuertes Eintragen von Inhalten in das Formular (bestimmte Validierungsprüfungen werden nur bei Nutzereingaben ausgeführt, nicht aber, wenn Sie den Wert eines Formularfelds mit JavaScript setzen).
Validieren Sie Formulardaten daher immer auch auf der Server-Seite, und zwar entsprechend der Validierung auf der Client-Seite.
Intrinsische und grundlegende Bedingungen
In HTML werden grundlegende Bedingungen auf zwei Arten festgelegt:
- Durch Auswahl des semantisch am besten geeigneten Werts für das Attribut
typedes Elements<input>. Die Auswahl des Typsemaillegt beispielsweise automatisch eine Bedingung fest, die prüft, ob der Wert eine gültige E-Mail-Adresse ist. - Durch Setzen von Werten für validierungsbezogene Attribute. So lassen sich grundlegende Bedingungen ohne JavaScript beschreiben.
Semantische Input-Typen
Für das Attribut type gelten folgende intrinsische Bedingungen:
| Input-Typ | Beschreibung der Bedingung | Zugehöriger Validierungsfehler |
|---|---|---|
<input type="URL"> |
Der Wert muss eine absolute URL gemäß dem URL Living Standard sein. | TypeMismatch-Validierungsfehler |
<input type="email"> |
Der Wert muss eine syntaktisch gültige E-Mail-Adresse sein. Diese hat im Allgemeinen das Format username@hostname.tld, kann aber auch lokal sein, etwa username@hostname. |
TypeMismatch-Validierungsfehler |
Wenn beim Input-Typ email das Attribut multiple gesetzt ist, können mehrere Werte als kommagetrennte Liste angegeben werden. Erfüllt einer der Werte in der Liste die hier beschriebene Bedingung nicht, wird der Validierungsfehler Type mismatch ausgelöst.
Beachten Sie, dass die meisten Input-Typen keine intrinsischen Bedingungen haben: Einige sind von der Constraint Validation ausgeschlossen, andere verfügen über einen Bereinigungsalgorithmus, der ungültige Werte in einen gültigen Standardwert umwandelt.
Validierungsbezogene Attribute
Zusätzlich zum oben beschriebenen Attribut type werden die folgenden Attribute verwendet, um grundlegende Bedingungen zu beschreiben:
| Attribut | Input-Typen, die das Attribut unterstützen | Mögliche Werte | Beschreibung der Bedingung | Zugehöriger Validierungsfehler |
|---|---|---|---|---|
pattern
|
text, search, url,
tel, email, password
|
Ein
regulärer JavaScript-Ausdruck
(kompiliert mit deaktivierten Flags global, ignoreCase und
multiline)
|
Der Wert muss dem Muster entsprechen. |
patternMismatch-Validierungsfehler
|
min
|
range, number |
Eine gültige Zahl | Der eingegebene Wert muss größer oder gleich dem Attributwert sein. |
rangeUnderflow-Validierungsfehler
|
date, month, week |
Ein gültiges Datum | |||
datetime-local, time
|
Ein gültiges Datum mit Uhrzeit | |||
max
|
range, number |
Eine gültige Zahl | Der eingegebene Wert muss kleiner oder gleich dem Attributwert sein. |
rangeOverflow-Validierungsfehler
|
date, month, week |
Ein gültiges Datum | |||
datetime-local, time
|
Ein gültiges Datum mit Uhrzeit | |||
required
|
text, search, url,
tel, email, password,
date, datetime-local,
month, week, time,
number, checkbox, radio,
file; außerdem bei den Elementen <select> und
<textarea>
|
Keiner, da es sich um ein boolesches Attribut handelt: Ist es vorhanden, bedeutet dies true, andernfalls false. | Wenn das Attribut gesetzt ist, muss ein Wert vorhanden sein. |
valueMissing-Validierungsfehler
|
step
|
date |
Eine ganzzahlige Anzahl von Tagen |
Sofern die Schrittweite nicht auf das Literal any gesetzt ist,
muss der Wert min plus einem ganzzahligen Vielfachen der Schrittweite entsprechen.
|
stepMismatch-Validierungsfehler
|
month |
Eine ganzzahlige Anzahl von Monaten | |||
week |
Eine ganzzahlige Anzahl von Wochen | |||
datetime-local, time
|
Eine ganzzahlige Anzahl von Sekunden | |||
range, number |
Eine Ganzzahl | |||
minlength
|
text, search, url,
tel, email, password; außerdem beim
Element <textarea>
|
Eine ganzzahlige Länge |
Wenn der Wert nicht leer ist, darf die Anzahl der Zeichen (Codepunkte) nicht
kleiner als der Attributwert sein. Bei <textarea> werden
alle Zeilenumbrüche zu einem einzelnen Zeichen normalisiert
(statt zu CRLF-Paaren).
|
tooShort-Validierungsfehler
|
maxlength
|
text, search, url,
tel, email, password; außerdem beim
Element <textarea>
|
Eine ganzzahlige Länge | Die Anzahl der Zeichen (Codepunkte) darf den Attributwert nicht überschreiten. |
tooLong-Validierungsfehler
|
Ablauf der Constraint Validation
Die Constraint Validation wird mithilfe der Constraint Validation API entweder für ein einzelnes Formularelement oder für das gesamte Formular über das Element <form> ausgeführt. Dafür gibt es folgende Möglichkeiten:
- Durch Aufruf der Methode
checkValidity()oderreportValidity()einer formularbezogenen DOM-Schnittstelle (HTMLInputElement,HTMLSelectElement,HTMLButtonElement,HTMLOutputElementoderHTMLTextAreaElement). Dabei werden nur die Bedingungen für dieses Element geprüft, sodass ein Skript das Ergebnis abrufen kann. Die MethodecheckValidity()gibt einen booleschen Wert zurück, der angibt, ob der Wert des Elements seine Bedingungen erfüllt. (Dies geschieht normalerweise durch den User-Agent, wenn er bestimmt, welche der CSS-Pseudoklassen:validoder:invalidzutrifft.) Die MethodereportValidity()hingegen meldet den Nutzern Verstöße gegen die Bedingungen. - Durch Aufruf der Methode
checkValidity()oderreportValidity()der SchnittstelleHTMLFormElement. - Durch Absenden des Formulars.
Der Aufruf von checkValidity() wird als statische Validierung der Bedingungen bezeichnet. Der Aufruf von reportValidity() oder das Absenden des Formulars wird als interaktive Validierung bezeichnet.
Hinweis:
- Wenn das Attribut
novalidatefür das Element<form>gesetzt ist, findet keine interaktive Validierung der Bedingungen statt. - Ein Aufruf der Methode
submit()der SchnittstelleHTMLFormElementlöst keine Constraint Validation aus. Anders ausgedrückt: Diese Methode sendet die Formulardaten auch dann an den Server, wenn sie die Bedingungen nicht erfüllen. Rufen Sie stattdessen die Methodeclick()auf einem Submit-Button auf. - Die Bedingungen
minlengthundmaxlengthwerden nur bei Nutzereingaben geprüft. Wird ein Wert programmgesteuert gesetzt, findet die Prüfung auch dann nicht statt, wenncheckValidity()oderreportValidity()ausdrücklich aufgerufen wird.
Komplexe Bedingungen mit der Constraint Validation API
Mit JavaScript und der Constraint Validation API können komplexere Bedingungen implementiert werden, beispielsweise Bedingungen, die mehrere Felder miteinander verknüpfen oder komplexe Berechnungen erfordern.
Grundsätzlich wird bei einem Ereignis eines Formularfelds (etwa onchange) JavaScript ausgeführt, um zu bestimmen, ob eine Bedingung verletzt ist. Anschließend wird mit der Methode field.setCustomValidity() das Ergebnis der Validierung festgelegt: Ein leerer String bedeutet, dass die Bedingung erfüllt ist. Jeder andere String bedeutet, dass ein Fehler vorliegt, und dient als Fehlermeldung für die Nutzer.
Bedingung für mehrere Felder: Postleitzahlvalidierung
Das Format von Postleitzahlen unterscheidet sich von Land zu Land. In vielen Ländern ist ein optionales Präfix mit dem Ländercode zulässig (etwa D- in Deutschland, F- in Frankreich und CH- in der Schweiz). In manchen Ländern bestehen Postleitzahlen nur aus einer festen Anzahl von Ziffern. Andere Länder wie das Vereinigte Königreich verwenden komplexere Formate, bei denen an bestimmten Stellen Buchstaben zulässig sind.
Hinweis: Dies ist keine umfassende Bibliothek zur Postleitzahlvalidierung, sondern eine Veranschaulichung der grundlegenden Konzepte.
Als Beispiel fügen wir einem Formular ein Skript hinzu, das die Bedingungen prüft:
<form>
<label for="postal-code">Postal Code: </label>
<input type="text" id="postal-code" />
<label for="country">Country: </label>
<select id="country">
<option value="ch">Switzerland</option>
<option value="fr">France</option>
<option value="de">Germany</option>
<option value="nl">The Netherlands</option>
</select>
<input type="submit" value="Validate" />
</form>
Dadurch wird das folgende Formular angezeigt:
Zuerst schreiben wir eine Funktion, die die Bedingung selbst prüft:
const countrySelect = document.getElementById("country");
const postalCodeField = document.getElementById("postal-code");
function checkPostalCode() {
// For each country, defines the pattern that the postal code has to follow
const constraints = {
ch: [
"^(CH-)?\\d{4}$",
"Swiss postal codes must have exactly 4 digits: e.g. CH-1950 or 1950",
],
fr: [
"^(F-)?\\d{5}$",
"French postal codes must have exactly 5 digits: e.g. F-75012 or 75012",
],
de: [
"^(D-)?\\d{5}$",
"German postal codes must have exactly 5 digits: e.g. D-12345 or 12345",
],
nl: [
"^(NL-)?\\d{4}\\s*([A-RT-Z][A-Z]|S[BCE-RT-Z])$",
"Dutch postal codes must have exactly 4 digits, followed by 2 letters except SA, SD and SS",
],
};
// Read the country id
const country = countrySelect.value;
// Build the constraint checker
const constraint = new RegExp(constraints[country][0], "");
console.log(constraint);
// Check it!
if (constraint.test(postalCodeField.value)) {
// The postal code follows the constraint, we use the ConstraintAPI to tell it
postalCodeField.setCustomValidity("");
} else {
// The postal code doesn't follow the constraint, we use the ConstraintAPI to
// give a message about the format required for this country
postalCodeField.setCustomValidity(constraints[country][1]);
}
}
Anschließend verknüpfen wir sie mit dem Ereignis change für <select> und dem Ereignis input für <input>:
countrySelect.addEventListener("change", checkPostalCode);
postalCodeField.addEventListener("input", checkPostalCode);
Dateigröße vor dem Upload begrenzen
Eine weitere häufige Bedingung ist die Begrenzung der Größe einer hochzuladenden Datei. Um dies auf der Client-Seite zu prüfen, bevor die Datei an den Server übertragen wird, muss die Constraint Validation API – insbesondere die Methode field.setCustomValidity() – mit einer weiteren JavaScript-API kombiniert werden, hier der File API.
Hier ist der HTML-Teil:
<label for="fs">Select a file smaller than 75 kB: </label>
<input type="file" id="fs" />
Damit wird Folgendes angezeigt:
Das JavaScript liest die ausgewählte Datei, ermittelt ihre Größe mit der Methode File.size(), vergleicht sie mit dem fest codierten Grenzwert und teilt dem Browser über die Constraint Validation API mit, ob die Bedingung verletzt ist:
const fs = document.getElementById("fs");
function checkFileSize() {
const files = fs.files;
// If there is (at least) one file selected
if (files.length > 0) {
if (files[0].size > 75 * 1000) {
// Check the constraint
fs.setCustomValidity("The selected file must not be larger than 75 kB");
fs.reportValidity();
return;
}
}
// No custom constraint violation
fs.setCustomValidity("");
}
Abschließend verknüpfen wir die Methode mit dem passenden Ereignis:
fs.addEventListener("change", checkFileSize);
Visuelle Gestaltung der Constraint Validation
Webentwickler möchten nicht nur Bedingungen festlegen, sondern auch steuern, welche Meldungen den Nutzern angezeigt werden und wie diese gestaltet sind.
Darstellung von Elementen steuern
Die Darstellung von Elementen kann über CSS-Pseudoklassen gesteuert werden.
CSS-Pseudoklassen :required und :optional
Mit den Pseudoklassen :required und :optional lassen sich Selektoren schreiben, die Formularelemente mit beziehungsweise ohne das Attribut required auswählen.
CSS-Pseudoklasse :placeholder-shown
Siehe :placeholder-shown.
CSS-Pseudoklassen :valid und :invalid
Die Pseudoklassen :valid und :invalid kennzeichnen <input>-Elemente, deren Inhalt entsprechend dem eingestellten Input-Typ gültig beziehungsweise ungültig ist. Mit diesen Klassen lassen sich gültige und ungültige Formularelemente gestalten, damit korrekt und falsch formatierte Eingaben leichter zu erkennen sind.
Text von Validierungsfehlermeldungen steuern
Die folgenden Möglichkeiten helfen dabei, den Text einer Validierungsfehlermeldung zu steuern:
-
Die Methode
setCustomValidity(message)für die folgenden Elemente:<fieldset>. Hinweis: Das Festlegen einer benutzerdefinierten Validierungsfehlermeldung für fieldset-Elemente verhindert in den meisten Browsern nicht, dass das Formular abgesendet wird.<input><output><select>- Submit-Buttons (erstellt entweder mit einem Element
<button>vom Typsubmitoder mit eineminput-Element vom Typ submit). Andere Button-Typen nehmen nicht an der Constraint Validation teil. <textarea>
-
Die Schnittstelle
ValidityStatebeschreibt das Objekt, das von der Eigenschaftvalidityder oben aufgeführten Elementtypen zurückgegeben wird. Sie bildet verschiedene Gründe ab, aus denen ein eingegebener Wert ungültig sein kann. So lässt sich nachvollziehen, warum der Wert eines Elements die Validierung nicht besteht.