Verwenden der HTML-Formularvalidierung und der Constraint Validation API
Das Erstellen von Webformularen war schon immer eine komplexe Aufgabe. Während das Markieren des Formulars selbst einfach ist, ist das Überprüfen, ob jedes Feld einen gültigen und kohärenten Wert hat, schwieriger, und den Benutzer über das Problem zu informieren, kann Kopfschmerzen bereiten. HTML5 führte neue Mechanismen für Formulare ein: Es fügte neue semantische Typen für das <input>
-Element hinzu und die Constraint-Validierung, um die Überprüfung des Formularinhalts auf der Clientseite zu erleichtern. Grundlegende, übliche Einschränkungen können ohne JavaScript durch das Setzen neuer Attribute überprüft werden; komplexere Einschränkungen können mit der Constraint Validation API getestet werden.
Für eine grundlegende Einführung in diese Konzepte mit Beispielen siehe das Formularvalidierungs-Tutorial.
Hinweis: Die HTML-Constraint-Validierung beseitigt nicht die Notwendigkeit der Validierung auf der Serverseite. Auch wenn viel weniger ungültige Formularanfragen zu erwarten sind, können ungültige weiterhin auf viele Arten gesendet werden:
- Durch Ändern des HTML-Codes über die Entwicklertools des Browsers.
- Durch manuelles Erstellen einer HTTP-Anfrage ohne Verwendung des Formulars.
- Durch das programmgesteuerte Schreiben von Inhalten in das Formular (bestimmte Constraint-Validierungen werden nur für Benutzereingaben ausgeführt und nicht, wenn Sie den Wert eines Formularfelds mit JavaScript setzen).
Daher sollten Sie Formulardaten immer auf der Serverseite validieren, konsistent mit dem, was auf der Clientseite gemacht wird.
Intrinsische und grundlegende Einschränkungen
In HTML werden grundlegende Einschränkungen auf zwei Arten deklariert:
- Durch das Wählen des semantisch geeignetsten Wertes für das
type
-Attribut des<input>
-Elements, z. B. durch das Wählen des Typsemail
, wodurch automatisch eine Einschränkung erstellt wird, die überprüft, ob der Wert eine gültige E-Mail-Adresse ist. - Durch das Setzen von Werten auf Validierungs-bezogene Attribute, die es ermöglichen, grundlegende Einschränkungen zu beschreiben, ohne dass JavaScript erforderlich ist.
Semantische Eingabetypen
Die intrinsischen Einschränkungen für das type
-Attribut sind:
Eingabetyp | Beschreibung der Einschränkung | Zugehörige Verletzung |
---|---|---|
<input type="URL"> |
Der Wert muss eine absolute URL sein, wie im URL Living Standard definiert. | TypeMismatch Einschränkungsverletzung |
<input type="email"> |
Der Wert muss eine syntaktisch gültige E-Mail-Adresse sein, die im Allgemeinen das Format [email protected] hat, aber auch lokal wie username@hostname sein kann. |
TypeMismatch Einschränkungsverletzung |
Für diese beiden Eingabetypen können bei gesetztem multiple
-Attribut mehrere Werte als kommagetrennte Liste festgelegt werden. Wenn einer dieser Werte die hier beschriebene Bedingung nicht erfüllt, wird die Type mismatch Einschränkungsverletzung ausgelöst.
Beachten Sie, dass die meisten Eingabetypen keine intrinsischen Einschränkungen haben, da einige von der Constraint-Validierung ausgeschlossen sind oder einen Bereinigungsalgorithmus haben, der falsche Werte in einen korrekten Standardwert umwandelt.
Validierungsbezogene Attribute
Zusätzlich zu dem oben beschriebenen type
-Attribut werden folgende Attribute zur Beschreibung grundlegender Einschränkungen verwendet:
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
JavaScript-Regular-Expression
(kompiliert mit deaktivierten global , ignoreCase und
multiline Flags)
|
Der Wert muss dem Muster entsprechen. |
patternMismatch
Einschränkungsverletzung
|
min
|
range , number |
Eine gültige Zahl | Der Wert muss größer oder gleich dem Wert sein. |
rangeUnderflow
Einschränkungsverletzung
|
date , month , week |
Ein gültiges Datum | |||
datetime-local , time
|
Ein gültiges Datum und Uhrzeit | |||
max
|
range , number |
Eine gültige Zahl | Der Wert muss kleiner oder gleich dem Wert sein |
rangeOverflow
Einschränkungsverletzung
|
date , month , week |
Ein gültiges Datum | |||
datetime-local , time
|
Ein gültiges Datum und Uhrzeit | |||
required
|
text , search , url ,
tel , email , password ,
date , datetime-local ,
month , week , time ,
number , checkbox , radio ,
file ; auch auf den <select> und
<textarea> Elementen
|
keiner, da es sich um ein Boolean-Attribut handelt: Seine Anwesenheit bedeutet wahr, seine Abwesenheit bedeutet falsch | Es muss ein Wert vorhanden sein (wenn gesetzt). |
valueMissing
Einschränkungsverletzung
|
step
|
date |
Eine ganze Zahl von Tagen |
Sofern der Schritt nicht auf das Literal any gesetzt ist, muss der Wert min + ein Vielfaches des Schritts sein.
|
stepMismatch
Einschränkungsverletzung
|
month |
Eine ganze Zahl von Monaten | |||
week |
Eine ganze Zahl von Wochen | |||
datetime-local , time
|
Eine ganze Zahl von Sekunden | |||
range , number |
Eine ganze Zahl | |||
minlength
|
text , search , url ,
tel , email , password ; auch auf dem
<textarea> -Element
|
Eine ganze Zahl der Länge |
Die Anzahl der Zeichen (Codepunkte) darf nicht niedriger als der Wert
des Attributs sein, wenn nicht leer. Alle Zeilenumbrüche werden zu einem
einzigen Zeichen (im Gegensatz zu CRLF-Paaren) für <textarea> normalisiert.
|
tooShort
Einschränkungsverletzung
|
maxlength
|
text , search , url ,
tel , email , password ; auch auf dem
<textarea> -Element
|
Eine ganze Zahl der Länge | Die Anzahl der Zeichen (Codepunkte) darf den Wert des Attributs nicht überschreiten. |
tooLong
Einschränkungsverletzung
|
Prozess der Constraint-Validierung
Die Constraint-Validierung wird durch die Constraint Validation API entweder auf einem einzelnen Formularelement oder auf Formularebene am <form>
-Element selbst durchgeführt. Die Constraint-Validierung erfolgt auf folgende Weise:
- Durch einen Aufruf der Methode
checkValidity()
oderreportValidity()
einer Formular-assoziierten DOM-Schnittstelle (HTMLInputElement
,HTMLSelectElement
,HTMLButtonElement
,HTMLOutputElement
oderHTMLTextAreaElement
), die die Einschränkungen nur für dieses Element auswertet, sodass ein Skript diese Informationen erhalten kann. DiecheckValidity()
-Methode gibt einen Boolean zurück, der anzeigt, ob der Wert des Elements seine Einschränkungen erfüllt. (Dies wird normalerweise vom Benutzer-Agenten getan, wenn er bestimmt, welche der CSS-Pseudoklassen,:valid
oder:invalid
, zutrifft.) Im Gegensatz dazu meldet diereportValidity()
-Methode dem Benutzer eventuelle Einschränkungsverstöße. - Durch einen Aufruf der Methode
checkValidity()
oderreportValidity()
auf derHTMLFormElement
-Schnittstelle. - Durch das Absenden des Formulars selbst.
Das Aufrufen von checkValidity()
wird als statische Validierung der Einschränkungen bezeichnet, während das Aufrufen von reportValidity()
oder das Absenden des Formulars als interaktive Validierung der Einschränkungen bezeichnet wird.
Hinweis:
- Wenn das
novalidate
-Attribut am<form>
-Element gesetzt ist, erfolgt keine interaktive Validierung der Einschränkungen. - Das Aufrufen der
submit()
-Methode auf derHTMLFormElement
-Schnittstelle löst keine Einschränkungsvalidierung aus. Mit anderen Worten, diese Methode sendet die Formulardaten an den Server, auch wenn sie die Einschränkungen nicht erfüllen. Rufen Sie stattdessen dieclick()
-Methode auf einer Schaltfläche zum Absenden auf. - Die
minlength
- undmaxlength
-Einschränkungen werden nur bei benutzergesteuerten Eingaben überprüft. Sie werden nicht überprüft, wenn ein Wert programmiert gesetzt wird, auch wenncheckValidity()
oderreportValidity()
explizit aufgerufen wird.
Komplexe Einschränkungen mit der Constraint Validation API
Mit JavaScript und der Constraint API ist es möglich, komplexere Einschränkungen zu implementieren, z. B. Einschränkungen, die mehrere Felder kombinieren, oder Einschränkungen, die komplexe Berechnungen beinhalten.
Grundsätzlich besteht die Idee darin, JavaScript bei einem Ereignis eines Formularelements (wie onchange) auszulösen, um zu berechnen, ob die Einschränkung verletzt wird, und dann die Methode field.setCustomValidity()
zu verwenden, um das Ergebnis der Validierung festzulegen: Ein leerer String bedeutet, dass die Einschränkung erfüllt ist, und jeder andere String bedeutet, dass ein Fehler vorliegt, und dieser String ist die Fehlermeldung, die dem Benutzer angezeigt wird.
Einschränkung, die mehrere Felder kombiniert: Postleitzahlenvalidierung
Das Postleitzahlenformat variiert von Land zu Land. Die meisten Länder erlauben nicht nur ein optionales Präfix mit dem Ländercode (wie D-
in Deutschland oder F-
in Frankreich oder der Schweiz), sondern einige Länder haben Postleitzahlen mit nur einer festen Anzahl von Ziffern; andere, wie das Vereinigte Königreich, haben komplexere Strukturen, die an bestimmten Positionen Buchstaben erlauben.
Hinweis: Dies ist keine umfassende Postleitzahlenvalidierungsbibliothek, sondern vielmehr eine Demonstration der Schlüsselkonzepte.
Als Beispiel fügen wir ein Skript hinzu, das die Constraint-Validierung für ein Formular überprü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>
Dies zeigt das folgende Formular an:
Zuerst schreiben wir eine Funktion, die die Einschränkung selbst überprüft:
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 = document.getElementById("country").value;
// Get the NPA field
const postalCodeField = document.getElementById("postal-code");
// 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]);
}
}
Dann verknüpfen wir sie mit dem onchange-Ereignis für das <select>
und dem oninput-Ereignis für das <input>
:
window.onload = () => {
document.getElementById("country").onchange = checkPostalCode;
document.getElementById("postal-code").oninput = checkPostalCode;
};
Begrenzung der Dateigröße vor dem Hochladen
Eine weitere häufige Einschränkung ist die Begrenzung der Größe einer Datei, die hochgeladen werden soll. Das Überprüfen dieser auf der Clientseite, bevor die Datei an den Server übertragen wird, erfordert die Kombination der Constraint Validation API, insbesondere die field.setCustomValidity()
-Methode, mit einer anderen JavaScript-API, 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" />
Dies zeigt:
Das JavaScript liest die ausgewählte Datei, verwendet die File.size()
-Methode, um ihre Größe zu bestimmen, vergleicht sie mit dem (fest codierten) Limit und ruft die Constraint API auf, um den Browser zu informieren, ob eine Verletzung vorliegt:
function checkFileSize() {
const fs = document.getElementById("fs");
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("");
}
Schließlich verbinden wir die Methode mit dem korrekten Ereignis:
window.onload = () => {
document.getElementById("fs").onchange = checkFileSize;
};
Visuelle Gestaltung der Constraint-Validierung
Neben dem Setzen von Einschränkungen möchten Webentwickler steuern, welche Nachrichten den Benutzern angezeigt werden und wie diese gestaltet sind.
Kontrolle des Aussehens von Elementen
Das Aussehen von Elementen kann über CSS-Pseudoklassen gesteuert werden.
:required und :optional CSS-Pseudoklassen
Die :required
und :optional
Pseudoklassen ermöglichen das Schreiben von Selektoren, die Formularelemente, die das required
-Attribut haben oder nicht haben, ansprechen.
:placeholder-shown CSS-Pseudoklasse
Siehe :placeholder-shown
.
:valid :invalid CSS-Pseudoklassen
Die :valid
und :invalid
Pseudoklassen werden verwendet, um <input>
-Elemente darzustellen, deren Inhalt gemäß der Einstellung des Typattributs gültig bzw. ungültig ist. Diese Klassen ermöglichen es, gültige oder ungültige Formularelemente zu stylen, um es einfacher zu machen, Elemente zu identifizieren, die entweder korrekt oder inkorrekt formatiert sind.
Kontrolle des Textes bei Einschränkungsverletzungen
Die folgenden Punkte können helfen, den Text bei einer Einschränkungsverletzung zu kontrollieren:
-
Die
setCustomValidity(message)
-Methode auf den folgenden Elementen:<fieldset>
. Hinweis: Das Setzen einer benutzerdefinierten Fehlernachricht auf Feldset-Elementen verhindert in den meisten Browsern nicht das Absenden des Formulars.<input>
<output>
<select>
- Abschicken von Schaltflächen (erstellt entweder mit einem
<button>
-Element mit demsubmit
-Typ oder eineminput
-Element mit dem submit-Typ. Andere Typen von Schaltflächen nehmen nicht an der Constraint-Validierung teil. <textarea>
-
Die
ValidityState
-Schnittstelle beschreibt das Objekt, das durch dievalidity
-Eigenschaft der oben aufgeführten Elementtypen zurückgegeben wird. Sie repräsentiert verschiedene Möglichkeiten, wie ein eingegebener Wert ungültig sein kann. Zusammen helfen sie zu erklären, warum ein Wert eines Elements die Validierung nicht besteht, wenn er nicht gültig ist.