Verwendung von HTML-Formularvalidierung und der Constraint Validation API
Die Erstellung von Webformularen war schon immer eine komplexe Aufgabe. Während das Markup des Formulars 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 und die Constraint-Validierung hinzu, um die Arbeit der Überprüfung des Formularinhalts auf der Clientseite 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 siehe das Formularvalidierungstutorial.
Hinweis: Die HTML-Constraint-Validierung entfernt nicht die Notwendigkeit für eine Validierung auf der Serverseite. Obwohl weit weniger ungültige Formularanforderungen zu erwarten sind, können ungültige dennoch auf viele Arten gesendet werden:
- Durch Ändern von HTML ü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 festlegen).
Daher sollten Sie Formulardaten immer auf der Serverseite validieren, konsistent mit dem, was auf der Clientseite getan wird.
Intrinsische und grundlegende Einschränkungen
In HTML werden grundlegende Einschränkungen auf zwei Arten deklariert:
- Durch die Auswahl des am besten semantisch passenden Werts für das
type
-Attribut des<input>
-Elements, z.B. erzeugt die Auswahl desemail
-Typs automatisch eine Einschränkung, die überprüft, ob der Wert eine gültige E-Mail-Adresse ist. - Durch Setzen von Werten für validierungsbezogene Attribute, die es ermöglichen, grundlegende Einschränkungen ohne die Notwendigkeit von JavaScript zu beschreiben.
Semantische Eingabetyps
Die inhärenten 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 in der URL Living Standard definiert. | TypeMismatch Constraint-Verletzung |
<input type="email"> |
Der Wert muss eine syntaktisch gültige E-Mail-Adresse sein, die im Allgemeinen das Format benutzername@hostname.tld hat, aber auch lokal wie benutzername@hostname sein kann. |
TypeMismatch Constraint-Verletzung |
Für beide Eingabetypen können, wenn das multiple
-Attribut gesetzt ist, mehrere Werte als kommagetrennte Liste festgelegt werden. Wenn einer dieser Werte die hier beschriebene Bedingung nicht erfüllt, wird die Type mismatch Constraint-Verletzung 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 |
---|---|---|---|---|
pattern
|
text , search , url ,
tel , email , password
|
Ein
JavaScript Regular Expression
(kompiliert mit den global , ignoreCase , und
multiline Flags deaktiviert)
|
Der Wert muss dem Muster entsprechen. |
patternMismatch
Constraint-Verletzung
|
min
|
range , number |
Eine gültige Zahl | Der Wert muss größer oder gleich dem Wert sein. |
rangeUnderflow
Constraint-Verletzung
|
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
Constraint-Verletzung
|
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 true, seine Abwesenheit bedeutet false | Es muss ein Wert sein (wenn gesetzt). |
valueMissing
Constraint-Verletzung
|
step
|
date |
Eine ganze Zahl von Tagen |
Sofern nicht explizit auf den Literal any gesetzt, muss der Wert
min + ein ganzzahliges Vielfaches des Schritts sein.
|
stepMismatch
Constraint-Verletzung
|
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 für die Länge |
Die Anzahl der Zeichen (Codepunkte) darf nicht kleiner sein als der Wert
des Attributs, wenn nicht leer. Alle neuen Zeilen sind auf ein einzelnes
Zeichen normalisiert (im Gegensatz zu CRLF-Paaren) für
<textarea> .
|
tooShort
Constraint-Verletzung
|
maxlength
|
text , search , url ,
tel , email , password ; auch auf dem
<textarea> Element
|
Eine ganze Zahl für die Länge | Die Anzahl der Zeichen (Codepunkte) darf den Wert des Attributs nicht überschreiten. |
tooLong
Constraint-Verletzung
|
Prozess der Constraint-Validierung
Die Constraint-Validierung wird entweder an einem einzelnen Formularelement oder auf Formularebene am <form>
-Element selbst über die Constraint Validation API durchgeführt. Die Validierung der Einschränkungen erfolgt auf folgende Weise:
- Durch einen Aufruf der
checkValidity()
- oderreportValidity()
-Methode eines formularzugehörigen DOM-Interfaces, (HTMLInputElement
,HTMLSelectElement
,HTMLButtonElement
,HTMLOutputElement
oderHTMLTextAreaElement
), was die Einschränkungen nur auf diesem Element evaluiert und es einem Skript ermöglicht, diese Informationen zu erhalten. DiecheckValidity()
-Methode gibt ein Boolean zurück, das angibt, ob der Wert des Elements seine Einschränkungen besteht. (Dies wird typischerweise vom Benutzeragenten durchgeführt, wenn er bestimmt, welcher der CSS-Pseudoklassen:valid
oder:invalid
zutrifft.) Im Gegensatz dazu meldet diereportValidity()
-Methode dem Benutzer etwaige Constraint-Verletzungen. - Durch einen Aufruf der
checkValidity()
- oderreportValidity()
-Methode auf demHTMLFormElement
-Interface. - Durch das Einreichen des Formulars selbst.
Der Aufruf von checkValidity()
wird als statische Validierung der Einschränkungen bezeichnet, während der Aufruf von reportValidity()
oder das Einreichen des Formulars als interaktive Validierung der Einschränkungen bezeichnet wird.
Hinweis:
- Wenn das
novalidate
-Attribut auf dem<form>
-Element gesetzt ist, erfolgt keine interaktive Validierung der Einschränkungen. - Der Aufruf der
submit()
-Methode auf demHTMLFormElement
-Interface löst keine Validierung der Einschränkung 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 einem Submit-Button auf. - Die
minlength
- undmaxlength
-Einschränkungen werden nur bei benutzereingebenden Eingaben überprüft. Sie werden nicht überprüft, wenn ein Wert programmgesteuert festgelegt ist, selbst wenncheckValidity()
oderreportValidity()
explizit aufgerufen wird.
Komplexe Einschränkungen mit der Constraint Validation API
Mit Hilfe von 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 beim Auftreten eines bestimmten Ereignisses im Formularfeld (wie onchange) auszuführen, 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 die Fehlermeldung ist, die dem Benutzer angezeigt werden soll.
Einschränkung, die mehrere Felder kombiniert: Postleitzahl-Validierung
Das Postleitzahlformat variiert von Land zu Land. Nicht nur erlauben die meisten Länder eine optionale Präfix mit dem Ländercode (wie D-
in Deutschland, 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 Buchstaben an bestimmten Positionen erlauben.
Hinweis: Dies ist keine umfassende Bibliothek zur Postleitzahlenvalidierung, 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 Größe einer Datei vor dem Hochladen
Eine weitere häufige Einschränkung ist die Begrenzung der Größe einer hochzuladenden Datei. Um dies auf der Clientseite zu überprüfen, bevor die Datei an den Server übertragen wird, muss die Constraint Validation API, insbesondere die field.setCustomValidity()
-Methode, mit einer anderen JavaScript API, hier der File API, kombiniert werden.
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 ermitteln, vergleicht sie mit dem (hartcodierten) 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 verknüpfen wir die Methode mit dem richtigen Ereignis:
window.onload = () => {
document.getElementById("fs").onchange = checkFileSize;
};
Visuelles Styling der Constraint-Validierung
Neben der Festlegung von Einschränkungen möchten Webentwickler die angezeigten Nachrichten kontrollieren 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 das Schreiben von Selektoren, die Formular-Elemente mit dem required
-Attribut oder solche ohne dieses Attribut auswählen.
:placeholder-shown CSS-Pseudoklasse
Siehe :placeholder-shown
.
:valid :invalid CSS-Pseudoklassen
Die :valid
und :invalid
Pseudoklassen werden verwendet, um <input>-Elemente darzustellen, deren Inhalt gültig ist oder nicht, entsprechend der Typ-Einstellung des Eingabefeldes. 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 inkorrekt formatiert sind.
Kontrolle des Textes bei Constraint-Verletzungen
Folgende Punkte können helfen, den Text einer Constraint-Verletzung zu kontrollieren:
-
Die
setCustomValidity(message)
-Methode auf den folgenden Elementen:<fieldset>
. Hinweis: Das Festlegen einer benutzerdefinierten Fehlermeldung auf Fieldset-Elementen hindert nicht daran, dass das Formular in den meisten Browsern übermittelt wird.<input>
<output>
<select>
- Submit-Buttons (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 stellt verschiedene Gründe dar, warum ein eingegebener Wert ungültig sein kann. Zusammen helfen sie zu erklären, warum ein Wert eines Elements nicht gültig ist, falls er es nicht ist.