HTML-Formularvalidierung und die Constraint Validation API verwenden
Das Erstellen von Webformularen war schon immer eine komplexe Aufgabe. Das Formular selbst auszuzeichnen ist einfach. Schwieriger ist es, zu prüfen, ob jedes Feld einen gültigen und stimmigen Wert enthält. Auch die Nutzer über Probleme zu informieren, kann aufwendig sein. HTML5 führte neue Mechanismen für Formulare ein: neue semantische Typen für das <input>-Element und die Validierung von Einschränkungen, die das Prüfen von Formularinhalten auf der Clientseite erleichtert. Einfache, übliche Einschränkungen lassen sich ohne JavaScript durch Attribute prüfen; komplexere Einschränkungen können mit der Constraint Validation API getestet werden.
Eine grundlegende Einführung in diese Konzepte mit Beispielen finden Sie im Tutorial zur Formularvalidierung.
Hinweis: Die HTML-Validierung von Einschränkungen ersetzt nicht die Validierung auf der Serverseite. Auch wenn deutlich weniger ungültige Formularanfragen zu erwarten sind, können solche Anfragen weiterhin auf verschiedene Weise gesendet werden:
- Durch Ändern des HTML-Codes mit den Entwicklertools des Browsers.
- Durch manuelles Erstellen einer HTTP-Anfrage, ohne das Formular zu verwenden.
- Durch programmgesteuertes Einfügen von Inhalten in das Formular (bestimmte Validierungen von Einschränkungen 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 Serverseite, und zwar nach denselben Regeln wie auf der Clientseite.
Intrinsische und grundlegende Einschränkungen
In HTML werden grundlegende Einschränkungen auf zwei Arten festgelegt:
- Durch die Wahl des semantisch passendsten Werts für das Attribut
typedes<input>-Elements. Beispielsweise legt der Typemailautomatisch eine Einschränkung fest, die prüft, ob der Wert eine gültige E-Mail-Adresse ist. - Durch das Setzen validierungsbezogener Attribute. Damit lassen sich grundlegende Einschränkungen ohne JavaScript beschreiben.
Semantische Eingabetypen
Für das Attribut type gelten folgende intrinsische Einschränkungen:
| Eingabetyp | Beschreibung der Einschränkung | Zugehörige Verletzung |
|---|---|---|
<input type="URL"> |
Der Wert muss eine absolute URL gemäß dem URL Living Standard sein. | Verletzung der Einschränkung TypeMismatch |
<input type="email"> |
Der Wert muss eine syntaktisch gültige E-Mail-Adresse sein. Sie hat im Allgemeinen das Format username@hostname.tld, kann aber auch lokal sein, etwa username@hostname. |
Verletzung der Einschränkung TypeMismatch |
Wenn beim Eingabetyp email das Attribut multiple gesetzt ist, können mehrere Werte als kommagetrennte Liste angegeben werden. Erfüllt ein Wert in der Liste die hier beschriebene Bedingung nicht, wird die Einschränkung Type mismatch verletzt.
Beachten Sie, dass die meisten Eingabetypen keine intrinsischen Einschränkungen haben: Manche sind von der Validierung von Einschränkungen ausgeschlossen, andere verwenden einen Bereinigungsalgorithmus, der ungültige Werte in einen gültigen Standardwert umwandelt.
Validierungsbezogene Attribute
Neben dem oben beschriebenen Attribut type werden die folgenden Attribute verwendet, um grundlegende Einschränkungen zu beschreiben:
| Attribut | Eingabetypen, die das Attribut unterstützen | Mögliche Werte | Beschreibung der Einschränkung | Zugehörige Verletzung |
|---|---|---|---|---|
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. |
Verletzung der Einschränkung
patternMismatch
|
min
|
range, number |
Eine gültige Zahl | Der Wert muss größer oder gleich dem Wert des Attributs sein. |
Verletzung der Einschränkung
rangeUnderflow
|
date, month, week |
Ein gültiges Datum | |||
datetime-local, time
|
Ein gültiges Datum und eine gültige Uhrzeit | |||
max
|
range, number |
Eine gültige Zahl | Der Wert muss kleiner oder gleich dem Wert des Attributs sein. |
Verletzung der Einschränkung
rangeOverflow
|
date, month, week |
Ein gültiges Datum | |||
datetime-local, time
|
Ein gültiges Datum und eine gültige 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>
|
Keine, 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. |
Verletzung der Einschränkung
valueMissing
|
step
|
date |
Eine ganze Anzahl von Tagen |
Sofern die Schrittweite nicht auf any gesetzt ist, muss der Wert
min plus einem ganzzahligen Vielfachen der Schrittweite entsprechen.
|
Verletzung der Einschränkung
stepMismatch
|
month |
Eine ganze Anzahl von Monaten | |||
week |
Eine ganze Anzahl von Wochen | |||
datetime-local, time
|
Eine ganze Anzahl von Sekunden | |||
range, number |
Eine ganze Zahl | |||
minlength
|
text, search, url,
tel, email, password; außerdem beim
<textarea>-Element
|
Eine ganzzahlige Länge |
Wenn der Wert nicht leer ist, darf die Anzahl der Zeichen (Codepoints) den
Wert des Attributs nicht unterschreiten. Bei <textarea>
werden alle Zeilenumbrüche zu einem einzelnen Zeichen normalisiert
(anstelle eines CRLF-Paars).
|
Verletzung der Einschränkung
tooShort
|
maxlength
|
text, search, url,
tel, email, password; außerdem beim
<textarea>-Element
|
Eine ganzzahlige Länge | Die Anzahl der Zeichen (Codepoints) darf den Wert des Attributs nicht überschreiten. |
Verletzung der Einschränkung
tooLong
|
Ablauf der Validierung von Einschränkungen
Die Validierung von Einschränkungen erfolgt über die Constraint Validation API, entweder für ein einzelnes Formularelement oder für das gesamte Formular über das <form>-Element. Sie kann auf folgende Weise ausgeführt werden:
- Durch Aufrufen der Methode
checkValidity()oderreportValidity()einer formularbezogenen DOM-Schnittstelle (HTMLInputElement,HTMLSelectElement,HTMLButtonElement,HTMLOutputElementoderHTMLTextAreaElement). Dabei werden nur die Einschränkungen dieses Elements 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 Einschränkungen erfüllt. (Dies geschieht üblicherweise durch den User-Agent, wenn er bestimmt, welche der CSS-Pseudoklassen:validoder:invalidzutrifft.) Die MethodereportValidity()hingegen meldet Nutzern alle Verletzungen von Einschränkungen. - Durch Aufrufen der Methode
checkValidity()oderreportValidity()auf der SchnittstelleHTMLFormElement. - Durch Absenden des Formulars.
Das Aufrufen von checkValidity() wird als statische Validierung der Einschränkungen bezeichnet. Das Aufrufen von reportValidity() oder das Absenden des Formulars gilt dagegen als interaktive Validierung.
Hinweis:
- Wenn das Attribut
novalidatebeim<form>-Element gesetzt ist, findet keine interaktive Validierung der Einschränkungen statt. - Das Aufrufen der Methode
submit()auf der SchnittstelleHTMLFormElementlöst keine Validierung der Einschränkungen aus. Die Methode sendet die Formulardaten also auch dann an den Server, wenn sie die Einschränkungen nicht erfüllen. Rufen Sie stattdessen die Methodeclick()einer Schaltfläche zum Absenden auf. - Die Einschränkungen
minlengthundmaxlengthwerden nur bei Nutzereingaben geprüft. Wird ein Wert programmgesteuert gesetzt, werden sie auch dann nicht geprüft, wenncheckValidity()oderreportValidity()ausdrücklich aufgerufen wird.
Komplexe Einschränkungen mit der Constraint Validation API
Mit JavaScript und der Constraint Validation API lassen sich komplexere Einschränkungen umsetzen, beispielsweise solche, die mehrere Felder kombinieren oder komplexe Berechnungen erfordern.
Das Grundprinzip besteht darin, bei einem Ereignis eines Formularfelds (etwa onchange) JavaScript auszuführen, um zu prüfen, ob die Einschränkung verletzt ist. Anschließend wird das Ergebnis der Validierung mit der Methode field.setCustomValidity() festgelegt: Eine leere Zeichenfolge bedeutet, dass die Einschränkung erfüllt ist. Jede andere Zeichenfolge bedeutet, dass ein Fehler vorliegt, und dient als Fehlermeldung für die Nutzer.
Einschränkung über mehrere Felder: Postleitzahlen validieren
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, etwa das Vereinigte Königreich, verwenden komplexere Formate, bei denen an bestimmten Stellen Buchstaben erlaubt sind.
Hinweis: Dies ist keine umfassende Bibliothek zur Validierung von Postleitzahlen, sondern eine Demonstration der wichtigsten Konzepte.
Als Beispiel fügen wir einem Formular ein Skript hinzu, das die Einschränkungen 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:
Zunächst schreiben wir eine Funktion, die die Einschränkung 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 das <select>-Element und dem Ereignis input für das <input>-Element:
countrySelect.addEventListener("change", checkPostalCode);
postalCodeField.addEventListener("input", checkPostalCode);
Dateigröße vor dem Hochladen begrenzen
Eine weitere häufige Einschränkung ist die maximale Größe einer hochzuladenden Datei. Um diese vor der Übertragung an den Server auf der Clientseite zu prüfen, 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" />
Das Ergebnis sieht so aus:
Das JavaScript liest die ausgewählte Datei, ermittelt ihre Größe mit der Methode File.size(), vergleicht sie mit dem fest im Code hinterlegten Grenzwert und informiert den Browser über die Constraint Validation API, falls die Einschränkung 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("");
}
Zum Schluss verknüpfen wir die Methode mit dem passenden Ereignis:
fs.addEventListener("change", checkFileSize);
Visuelle Gestaltung der Validierung von Einschränkungen
Neben dem Festlegen von Einschränkungen möchten Webentwickler steuern, welche Meldungen Nutzern angezeigt werden und wie diese gestaltet sind.
Darstellung von Elementen steuern
Die Darstellung von Elementen lässt sich mit CSS-Pseudoklassen steuern.
CSS-Pseudoklassen :required und :optional
Mit den Pseudoklassen :required und :optional lassen sich Selektoren für Formularelemente schreiben, die das Attribut required haben beziehungsweise nicht haben.
CSS-Pseudoklasse :placeholder-shown
Siehe :placeholder-shown.
CSS-Pseudoklassen :valid und :invalid
Die Pseudoklassen :valid und :invalid kennzeichnen <input>-Elemente, deren Inhalt gemäß dem festgelegten Eingabetyp gültig beziehungsweise ungültig ist. Mit diesen Klassen können gültige und ungültige Formularelemente unterschiedlich gestaltet werden, damit korrekt und falsch formatierte Eingaben leichter zu erkennen sind.
Text von Meldungen zu verletzten Einschränkungen steuern
Mit den folgenden Möglichkeiten lässt sich der Text einer Meldung zu einer verletzten Einschränkung steuern:
-
Die Methode
setCustomValidity(message)bei folgenden Elementen:<fieldset>. Hinweis: Das Festlegen einer benutzerdefinierten Validierungsmeldung für fieldset-Elemente verhindert in den meisten Browsern nicht das Absenden des Formulars.<input><output><select>- Schaltflächen zum Absenden (erstellt entweder mit einem
<button>-Element vom Typsubmitoder eineminput-Element vom Typ submit). Andere Schaltflächentypen nehmen nicht an der Validierung von Einschränkungen teil. <textarea>
-
Die Schnittstelle
ValidityStatebeschreibt das Objekt, das die Eigenschaftvalidityder oben aufgeführten Elementtypen zurückgibt. Sie bildet die verschiedenen Gründe ab, aus denen ein eingegebener Wert ungültig sein kann. Dadurch lässt sich nachvollziehen, warum der Wert eines Elements die Validierung nicht besteht.