Verwendung von HTML-Formularvalidierung und der Constraint Validation API
Die Erstellung von Webformularen war schon immer eine komplexe Aufgabe. Zwar ist das Markieren des Formulars selbst einfach, jedoch ist die Überprüfung, ob jedes Feld einen gültigen und kohärenten Wert hat, schwieriger, und den Benutzer über das Problem zu informieren kann zu einer Herausforderung werden. HTML5 hat neue Mechanismen für Formulare eingeführt: Es fügte neue semantische Typen für das <input>-Element und die Constraint-Validierung hinzu, um die Überprüfung des Formularinhalts auf der Client-Seite zu erleichtern. Grundlegende, übliche Einschränkungen können ohne JavaScript überprüft werden, indem neue Attribute gesetzt werden; komplexere Einschränkungen können mit der Constraint Validation API getestet werden.
Für eine grundlegende Einführung in diese Konzepte, mit Beispielen, lesen Sie das Formularvalidierung Tutorial.
Hinweis: Die HTML-Constraint-Validierung ersetzt nicht die Notwendigkeit der Validierung auf der Server-Seite. Auch wenn deutlich weniger ungültige Formularanfragen zu erwarten sind, können ungültige dennoch auf viele Weisen gesendet werden:
- Durch Veränderung von HTML über die Entwickler-Tools des Browsers.
- Durch manuelles Erstellen einer HTTP-Anfrage ohne Verwendung des Formulars.
- Durch programmatische Inhalteingabe in das Formular (bestimmte Constraint-Validierungen werden nur für Benutzereingaben durchgeführt und nicht, wenn Sie den Wert eines Formularfelds mit JavaScript setzen).
Daher sollten Sie stets sicherstellen, dass Formulardaten auf der Server-Seite validiert werden, in Übereinstimmung mit dem, was auf der Client-Seite getan wird.
Intrinsische und grundlegende Einschränkungen
In HTML werden grundlegende Einschränkungen auf zwei Arten deklariert:
- Durch Auswahl des semantisch passendsten Wertes für das
type-Attribut des<input>-Elements, z. B. erzeugt die Wahl desemailTyps automatisch eine Einschränkung, die überprüft, ob der Wert eine gültige E-Mail-Adresse ist. - Durch das Setzen von Werten auf validierungsbezogenen Attributen, die grundlegende Einschränkungen beschreiben, ohne dass JavaScript benötigt wird.
Semantische Input-Typen
Die intrinsischen Einschränkungen für das type-Attribut sind:
| Eingabetyp | Beschreibung der Einschränkung | Zugehörige Verletzung der Einschränkung |
|---|---|---|
<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 username@hostname.tld hat, aber auch lokal wie username@hostname sein kann. |
TypeMismatch Einschränkungsverletzung |
Für beide dieser Eingabetypen, wenn das multiple-Attribut gesetzt ist, können mehrere Werte als durch Kommas getrennte Liste gesetzt werden. Wenn eine dieser Bedingungen nicht erfüllt wird, 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 zum oben beschriebenen type-Attribut 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 der Einschränkung |
|---|---|---|---|---|
pattern
|
text, search, url,
tel, email, password
|
Ein
JavaScript-Regulärer Ausdruck
(kompiliert mit den global, ignoreCase, und
multiline Flags deaktiviert)
|
Der Wert muss mit dem Muster übereinstimmen. |
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
|
keine da es sich um ein Boolean-Attribut handelt: Seine Anwesenheit bedeutet wahr, seine Abwesenheit bedeutet false | Es muss ein Wert vorhanden sein (wenn gesetzt). |
valueMissing
Einschränkungsverletzung
|
step
|
date |
Eine ganzzahlige Anzahl von Tagen |
Es sei denn, der Schritt ist auf das Literal any gesetzt, der Wert muss
min + ein ganzzahliges Vielfaches des Schritts sein.
|
stepMismatch
Einschränkungsverletzung
|
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; auch auf dem
<textarea> Element
|
Eine ganzzahlige Länge |
Die Anzahl der Zeichen (Codepunkte) darf nicht geringer sein als der Wert des Attributs, wenn nicht leer. Alle Zeilenumbrüche werden zu einem einzigen Zeichen normalisiert (im Gegensatz zu CRLF-Paaren) für <textarea>.
|
tooShort
Einschränkungsverletzung
|
maxlength
|
text, search, url,
tel, email, password; auch auf dem
<textarea> Element
|
Eine ganzzahlige Länge | Die Anzahl der Zeichen (Codepunkte) darf den Wert des Attributs nicht überschreiten. |
tooLong
Einschränkungsverletzung
|
Prozess der Constraint-Validierung
Die Constraint-Validierung erfolgt über die Constraint Validation API entweder auf einem einzelnen Formularelement oder auf der Formularebene, auf dem <form>-Element selbst. Die Constraint-Validierung erfolgt in den folgenden Weisen:
- Durch einen Aufruf der
checkValidity()oderreportValidity()Methode eines formularassoziierten DOM-Interfaces (HTMLInputElement,HTMLSelectElement,HTMLButtonElement,HTMLOutputElementoderHTMLTextAreaElement), die die Einschränkungen nur auf diesem Element auswertet, um ein Skript diese Informationen erhalten zu lassen. DiecheckValidity()Methode gibt einen Boolean zurück, der anzeigt, ob der Wert des Elements seine Einschränkungen erfüllt. (Dies wird typischerweise vom Benutzeragenten getan, um zu bestimmen, welche der CSS-Pseudoklassen,:validoder:invalid, angewendet wird.) Im Gegensatz dazu meldet diereportValidity()Methode dem Benutzer etwaige Einschränkungsfehler. - Durch einen Aufruf der
checkValidity()oderreportValidity()Methode auf demHTMLFormElementInterface. - Durch das Absenden des Formulars selbst.
Der Aufruf von checkValidity() wird als statische Validierung der Einschränkungen bezeichnet, während der Aufruf von reportValidity() oder das Absenden des Formulars als interaktive Validierung der Einschränkungen bezeichnet wird.
Hinweis:
- Wenn das
novalidate-Attribut auf dem<form>-Element gesetzt ist, tritt keine interaktive Validierung der Einschränkungen ein. - Der Aufruf der
submit()Methode auf demHTMLFormElementInterface löst keine Einschränkungsvalidierung aus. Mit anderen Worten, diese Methode sendet die Formulardaten an den Server, selbst wenn sie die Einschränkungen nicht erfüllen. Rufen Sie stattdessen dieclick()Methode auf einer Sende-Schaltfläche auf. - Die
minlength- undmaxlength-Einschränkungen werden nur bei benutzerbereitgestellten Eingaben überprüft. Sie werden nicht überprüft, wenn ein Wert programmatisch gesetzt wird, selbst wenn man explizitcheckValidity()oderreportValidity()aufruft.
Komplexe Einschränkungen mittels der Constraint Validation API
Mithilfe von JavaScript und der Constraint API ist es möglich, komplexere Einschränkungen zu implementieren, zum Beispiel Einschränkungen, die mehrere Felder kombinieren, oder Einschränkungen, die komplexe Berechnungen beinhalten.
Grundsätzlich besteht die Idee darin, JavaScript bei einem bestimmten Ereignis eines Formularfelds (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 aufgetreten ist und dieser String die Fehlermeldung ist, die dem Benutzer angezeigt wird.
Einschränkung mehrerer Felder: Postleitzahlenvalidierung
Das Format der Postleitzahlen variiert von Land zu Land. Viele Länder erlauben ein optionales Präfix mit dem Ländercode (wie D- in Deutschland, F- in Frankreich und CH- in der Schweiz). Einige Länder verwenden nur eine feste Anzahl von Ziffern in Postleitzahlen, während andere, wie das Vereinigte Königreich, komplexere Formate haben, die Buchstaben an bestimmten Positionen erlauben.
Hinweis: Dies ist keine umfassende Bibliothek zur Postleitzahlenvalidierung, sondern eher eine Demonstration der Schlüsselkonzepte.
Als Beispiel werden wir ein Skript hinzufügen, 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 folgendes Formular an:
Zuerst schreiben wir eine Funktion, die die Einschränkung selbst überprü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]);
}
}
Dann verknüpfen wir sie mit dem change-Ereignis für das <select> und dem input-Ereignis für das <input>:
countrySelect.addEventListener("change", checkPostalCode);
postalCodeField.addEventListener("input", checkPostalCode);
Begrenzung der Dateigröße vor dem Hochladen
Eine weitere übliche Einschränkung ist die Begrenzung der Größe einer hochzuladenden Datei. Die Überprüfung auf der Client-Seite, bevor die Datei an den Server übertragen wird, erfordert die Kombination der Constraint Validation API und insbesondere der field.setCustomValidity() Methode mit einer anderen JavaScript-API, hier der File API.
Hier ist der HTML-Part:
<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 erhalten, vergleicht sie mit dem (hart kodierten) Limit und ruft die Constraint API auf, um den Browser zu informieren, ob eine Verletzung vorliegt:
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("");
}
Schließlich verbinden wir die Methode mit dem richtigen Ereignis:
fs.addEventListener("change", checkFileSize);
Visuelles Styling der Constraint-Validierung
Neben dem Setzen von Einschränkungen möchten Webentwickler kontrollieren, welche Nachrichten den Benutzern angezeigt werden und wie sie gestaltet werden.
Steuerung des Erscheinungsbildes von Elementen
Das Erscheinungsbild von Elementen kann über CSS-Pseudoklassen gesteuert werden.
:required und :optional CSS-Pseudoklassen
Die :required und :optional Pseudo-Klassen ermöglichen es, Selektoren zu schreiben, die Formularelemente auswählen, die das required Attribut haben oder nicht haben.
:placeholder-shown CSS-Pseudoklasse
Siehe :placeholder-shown.
:valid :invalid CSS-Pseudoklassen
Die :valid und :invalid Pseudo-Klassen werden verwendet, um <input>-Elemente darzustellen, deren Inhalt gemäß der Typeneinstellung des Eingabefelds validiert bzw. nicht validiert wird. Diese Klassen ermöglichen es dem Benutzer, gültige oder ungültige Formularelemente zu stylen, um es einfacher zu machen, Elemente zu identifizieren, die entweder korrekt oder falsch formatiert sind.
Steuerung des Textes der Einschränkungsverletzung
Folgende Punkte können helfen, den Text einer Einschränkungsverletzung zu steuern:
-
Die
setCustomValidity(message)Methode auf den folgenden Elementen:<fieldset>. Hinweis: Das Setzen einer benutzerdefinierten Fehlermeldung auf fieldset-Elemente verhindert nicht die Formularübermittlung in den meisten Browsern.<input><output><select>- Sende-Schaltflächen (erstellt mit entweder einem
<button>Element mit demsubmit-Typ, oder eineminputElement mit dem submit Typ. Andere Arten von Schaltflächen nehmen nicht an der Constraint-Validierung teil. <textarea>
-
Das
ValidityStateInterface beschreibt das Objekt, das von dervalidity-Eigenschaft der oben aufgelisteten Elementtypen zurückgegeben wird. Es stellt verschiedene Möglichkeiten dar, wie ein eingegebener Wert ungültig sein kann. Zusammen helfen sie zu erklären, warum der Wert eines Elements nicht gültig ist, falls er es nicht ist.