Verwendung der HTML-Formularvalidierung und der Constraint Validation API
Die Erstellung von Webformularen war schon immer eine komplexe Aufgabe. Während das Markieren des Formulars selbst einfach ist, ist es schwieriger, zu überprüfen, ob jedes Feld einen gültigen und kohärenten Wert hat. 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 und die Constraint-Validierung hinzu, um die Prüfung des Formularinhalts auf der Client-Seite zu erleichtern. Grundlegende, übliche Einschränkungen können ohne JavaScript überprüft werden, indem neue Attribute festgelegt 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 Server-Seite. Auch wenn weit weniger ungültige Formularanfragen zu erwarten sind, können ungültige dennoch auf viele Arten gesendet werden:
- Durch Änderung von HTML über die Entwicklertools des Browsers.
- Durch manuelles Erstellen einer HTTP-Anfrage ohne Verwendung des Formulars.
- Durch programmgesteuertes Schreiben von Inhalten in das Formular (bestimmte Constraint-Validierungen werden nur für Benutzereingaben ausgeführt und nicht, wenn Sie den Wert eines Formularfeldes mit JavaScript setzen).
Daher sollten Sie Formulardaten immer auf der Server-Seite validieren, konsistent mit dem, was auf der Client-Seite gemacht wird.
Intrinsische und grundlegende Einschränkungen
In HTML werden grundlegende Einschränkungen auf zwei Arten deklariert:
- Durch die Wahl des semantisch passendsten Werts für das
type-Attribut des<input>-Elements, z.B. erzeugt die Wahl desemail-Typs automatisch eine Einschränkung, die prüft, ob der Wert eine gültige E-Mail-Adresse ist. - Durch das Setzen von Werten auf validierungsbezogene Attribute, wodurch grundlegende Einschränkungen ohne die Notwendigkeit von JavaScript beschrieben werden können.
Semantische Input-Typen
Die intrinsischen Einschränkungen für das type-Attribut sind:
| Eingabetyp | Beschreibung der Einschränkung | Zugehöriger Verstoß |
|---|---|---|
<input type="URL"> |
Der Wert muss eine absolute URL sein, wie im URL Living Standard definiert. | TypeMismatch Einschränkungsverstoß |
<input type="email"> |
Der Wert muss eine syntaktisch gültige E-Mail-Adresse sein, die allgemein das Format username@hostname.tld hat, aber kann auch lokal wie username@hostname sein. |
TypeMismatch Einschränkungsverstoß |
Für den email-Eingabetyp, wenn das multiple-Attribut gesetzt ist, können mehrere Werte als kommagetrennte Liste gesetzt werden. Wenn irgendein Wert in der Liste die hier beschriebene Bedingung nicht erfüllt, wird der Type mismatch Einschränkungsverstoß ausgelöst.
Beachten Sie, dass die meisten Eingabetypen keine intrinsischen Einschränkungen haben, da einige von der Constraint-Validierung ausgeschlossen oder einen Bereinigungsalgorithmus haben, der falsche Werte in einen korrekten Standardwert umwandelt.
Validierungsbezogene Attribute
Zusätzlich zu dem 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öriger Verstoß |
|---|---|---|---|---|
pattern
|
text, search, url,
tel, email, password
|
Ein
JavaScript-Regulärer Ausdruck
(kompiliert mit den global, ignoreCase, und
multiline Flags deaktiviert)
|
Der Wert muss dem Muster entsprechen. |
patternMismatch
Einschränkungsverstoß
|
min
|
range, number |
Eine gültige Zahl | Der Wert muss größer oder gleich dem Wert sein. |
rangeUnderflow
Einschränkungsverstoß
|
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änkungsverstoß
|
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 bei den <select> und
<textarea> Elementen
|
keines da es ein Boolean-Attribut ist: seine Anwesenheit bedeutet wahr, seine Abwesenheit bedeutet falsch | Es muss ein Wert vorhanden sein (wenn gesetzt). |
valueMissing
Einschränkungsverstoß
|
step
|
date |
Eine ganze Anzahl von Tagen |
Sofern der Schritt nicht auf den any Literal gesetzt wird, muss der Wert
min + ein Vielfaches des Schritts sein.
|
stepMismatch
Einschränkungsverstoß
|
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; auch auf dem
<textarea> Element
|
Eine ganzzahlige Länge |
Die Anzahl der Zeichen (Codepunkte) darf nicht kleiner als der Wert des
Attributs sein, wenn nicht leer. Alle Zeilenumbrüche werden zu einem
einzelnen Zeichen normalisiert (im Gegensatz zu CRLF-Paaren) für
<textarea>.
|
tooShort
Einschränkungsverstoß
|
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änkungsverstoß
|
Prozess der Constraint-Validierung
Die Constraint-Validierung erfolgt über die Constraint Validation API entweder auf einem einzelnen Formularelement oder auf der Formular-Ebene, auf dem <form> selbst. Die Constraint-Validierung erfolgt auf folgende Weise:
- Durch einen Aufruf der
checkValidity()- oderreportValidity()-Methode einer formular-assoziierten DOM-Schnittstelle (HTMLInputElement,HTMLSelectElement,HTMLButtonElement,HTMLOutputElementoderHTMLTextAreaElement), die die Einschränkungen nur auf diesem Element überprüft und einem Skript ermöglicht, diese Information zu erhalten. DiecheckValidity()-Methode gibt einen Boolean-Wert zurück, der angibt, ob der Wert des Elements seine Einschränkungen besteht. (Dies wird typischerweise durch den Benutzagenten getan, um zu bestimmen, welche der CSS-Pseudoklassen,:validoder:invalid, angewendet wird.) Im Gegensatz dazu meldet diereportValidity()-Methode dem Benutzer alle Einschränkungsverstöße. - Durch einen Aufruf der
checkValidity()- oderreportValidity()-Methode auf derHTMLFormElement-Schnittstelle. - 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, findet keine interaktive Validierung der Einschränkungen statt. - Der Aufruf der
submit()-Methode auf derHTMLFormElement-Schnittstelle löst keine Constraint-Validierung 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 einem Submit-Button auf. - Die Einschränkungen
minlengthundmaxlengthwerden nur bei benutzerdefinierten Eingaben überprüft. Sie werden nicht überprüft, wenn ein Wert programmgesteuert gesetzt wird, selbst 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 bestimmten Formularfeldevent (wie onchange) auszulösen, um zu berechnen, ob die Einschränkung verletzt ist, und dann die Methode field.setCustomValidity() zu verwenden, um das Ergebnis der Validierung festzulegen: Ein leerer String bedeutet, die Einschränkung ist erfüllt, und jeder andere String bedeutet, es liegt ein Fehler vor, und dieser String ist die Fehlermeldung, die dem Benutzer angezeigt wird.
Einschränkung, die mehrere Felder kombiniert: Postleitzahlvalidierung
Das Format der Postleitzahl variiert von Land zu Land. Viele Länder erlauben eine optionale 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 an bestimmten Positionen Buchstaben erlauben.
Hinweis: Dies ist keine umfassende Bibliothek zur Postleitzahlvalidierung, sondern 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:
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 verbinden wir es mit dem change-Event für das <select> und dem input-Event für das <input>:
countrySelect.addEventListener("change", checkPostalCode);
postalCodeField.addEventListener("input", checkPostalCode);
Begrenzung der Dateigröße vor dem Upload
Eine weitere häufige Einschränkung besteht darin, die Größe einer Datei zu beschränken, die hochgeladen werden soll. Um dies auf der Clientseite zu überprüfen, bevor die Datei an den Server übertragen wird, muss die Constraint Validation API mit einer anderen JavaScript-API kombiniert werden, hier die File API, insbesondere die Methode field.setCustomValidity().
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 Methode File.size(), um ihre Größe zu ermitteln, vergleicht sie mit dem (fest kodierten) Limit und ruft die Constraint API auf, um den Browser zu informieren, ob ein Verstoß 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 verknüpfen wir die Methode mit dem richtigen Event:
fs.addEventListener("change", checkFileSize);
Visuelles Styling der Constraint-Validierung
Abgesehen vom Festlegen von Einschränkungen möchten Webentwickler kontrollieren, welche Nachrichten den Benutzern angezeigt werden und wie sie 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 erlauben es, Selektoren zu schreiben, die Formularelemente abgleichen, die das required-Attribut haben oder nicht haben.
:placeholder-shown CSS-Pseudoklasse
Siehe :placeholder-shown.
:valid :invalid CSS-Pseudoklassen
Die :valid und :invalid Pseudoklassen repräsentieren <input>-Elemente, deren Inhalt gemäß der Typeneinstellung des Inputs entweder validiert oder nicht validiert wird. Diese Klassen erlauben es dem Benutzer, 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 Verletzung der Einschränkungen
Die folgenden Punkte können helfen, den Text bei einer Verletzung der Einschränkung zu kontrollieren:
-
Die
setCustomValidity(message)-Methode auf den folgenden Elementen:<fieldset>. Hinweis: Das Setzen einer benutzerdefinierten Fehlermeldung auf fieldset-Elementen verhindert in den meisten Browsern nicht das Absenden des Formulars.<input><output><select>- Senden-Buttons (erstellt entweder mit einem
<button>-Element mit demsubmit-Typ oder eineminput-Element mit dem submit-Typ. Andere Button-Typen nehmen nicht an der Constraint-Validierung teil. <textarea>
-
Die
ValidityState-Schnittstelle beschreibt das Objekt, das von dervalidity-Eigenschaft der oben aufgelisteten Elementtypen zurückgegeben wird. Es repräsentiert verschiedene Möglichkeiten, wie ein eingegebener Wert ungültig sein kann. Zusammen helfen sie zu erklären, warum der Wert eines Elements nicht validiert, wenn er nicht gültig ist.