In meinem letzten Artikel habe ich Ihnen gezeigt, wie Sie die native Formularvalidierung des Browsers mithilfe einer Kombination aus semantischen Eingabetypen (z. B. <input type="email">) und Validierungsattributen (wie required und pattern) verwenden können.
Obwohl dieser Ansatz unglaublich einfach und super leichtgewichtig ist, hat er einige Nachteile.
- Sie können Felder mit Fehlern mit dem Pseudoselektor
:invalidgestalten, aber Sie können die Fehlermeldungen selbst nicht gestalten. - Das Verhalten ist auch browserübergreifend inkonsistent.
Benutzerstudien von Christian Holst und Luke Wroblewski (getrennt voneinander) ergaben, dass die Anzeige eines Fehlers, wenn der Benutzer ein Feld verlässt, und die Beibehaltung dieses Fehlers, bis das Problem behoben ist, die beste und schnellste Benutzererfahrung bietet.
Leider verhalten sich die Browser von Haus aus nicht so. Es gibt jedoch eine Möglichkeit, dieses Verhalten zu erzielen, ohne von einer großen JavaScript-Formularvalidierungsbibliothek abhängig zu sein.
Artikelserie
- Constraint-Validierung in HTML
- Die Constraint Validation API in JavaScript (Sie sind hier!)
- Ein Validity State API Polyfill
- Validierung des MailChimp-Anmeldeformulars
Die Constraint Validation API
Zusätzlich zu HTML-Attributen bietet die native Browser-Constraint-Validierung auch eine JavaScript-API, mit der wir das Verhalten unserer Formularvalidierung anpassen können.
Die API bietet einige verschiedene Methoden, aber die leistungsfähigste, der Validity State, ermöglicht es uns, die eigenen Feldvalidierungsalgorithmen des Browsers in unseren Skripten zu verwenden, anstatt eigene zu schreiben.
In diesem Artikel zeige ich Ihnen, wie Sie den Validity State verwenden, um das Verhalten, das Erscheinungsbild und den Inhalt Ihrer Formularvalidierungsfehlermeldungen anzupassen.
Validity State
Die Eigenschaft validity liefert eine Reihe von Informationen über ein Formularfeld in Form von Booleschen Werten (true/false).
var myField = document.querySelector('input[type="text"]');
var validityState = myField.validity;
Das zurückgegebene Objekt enthält die folgenden Eigenschaften:
valid– Isttrue, wenn das Feld die Validierung besteht.valueMissing– Isttrue, wenn das Feld leer, aber erforderlich ist.typeMismatch– Isttrue, wenn dertypedes Feldesemailoderurlist, aber der eingegebenevaluenicht vom korrekten Typ ist.tooShort– Isttrue, wenn das Feld einminLength-Attribut enthält und der eingegebenevaluekürzer als diese Länge ist.tooLong– Isttrue, wenn das Feld einmaxLength-Attribut enthält und der eingegebenevaluelänger als diese Länge ist.patternMismatch– Isttrue, wenn das Feld einpattern-Attribut enthält und der eingegebenevaluenicht mit dem Muster übereinstimmt.badInput– Isttrue, wenn der Eingabetypnumberist und der eingegebenevaluekeine Zahl ist.stepMismatch– Isttrue, wenn das Feld einstep-Attribut hat und der eingegebenevaluenicht den Schrittwerten entspricht.rangeOverflow– Isttrue, wenn das Feld einmax-Attribut hat und der eingegebene numerischevaluegrößer als das Maximum ist.rangeUnderflow– Isttrue, wenn das Feld einmin-Attribut hat und der eingegebene numerischevaluekleiner als das Minimum ist.
Durch die Verwendung der validity-Eigenschaft in Verbindung mit unseren Eingabetypen und HTML-Validierungsattributen können wir ein robustes Formularvalidierungsskript erstellen, das eine großartige Benutzererfahrung mit relativ wenig JavaScript bietet.
Legen wir los!
Native Formularvalidierung deaktivieren
Da wir unser eigenes Validierungsskript schreiben, möchten wir die native Browser-Validierung deaktivieren, indem wir das Attribut novalidate zu unseren Formularen hinzufügen. Wir können die Constraint Validation API weiterhin verwenden – wir möchten nur verhindern, dass die nativen Fehlermeldungen angezeigt werden.
Als Best Practice sollten wir dieses Attribut mit JavaScript hinzufügen, damit die native Browser-Formularvalidierung weiterhin funktioniert, falls unser Skript einen Fehler hat oder nicht geladen wird.
// Add the novalidate attribute when the JS loads
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].setAttribute('novalidate', true);
}
Es kann einige Formulare geben, die Sie nicht validieren möchten (z. B. ein Suchformular, das auf jeder Seite angezeigt wird). Anstatt unser Validierungsskript auf alle Formulare anzuwenden, wenden wir es nur auf Formulare mit der Klasse .validate an.
// Add the novalidate attribute when the JS loads
var forms = document.querySelectorAll('.validate');
for (var i = 0; i < forms.length; i++) {
forms[i].setAttribute('novalidate', true);
}
Siehe den Pen Form Validation: Add `novalidate` programatically von Chris Ferdinandi (@cferdinandi) auf CodePen.
Gültigkeit prüfen, wenn der Benutzer das Feld verlässt
Immer wenn ein Benutzer ein Feld verlässt, wollen wir prüfen, ob es gültig ist. Dazu richten wir einen Event-Listener ein.
Anstatt einen Listener für jedes Formularfeld hinzuzufügen, verwenden wir eine Technik namens Event Bubbling (oder Event Propagation), um auf alle blur-Ereignisse zu lauschen.
// Listen to all blur events
document.addEventListener('blur', function (event) {
// Do something on blur...
}, true);
Sie werden feststellen, dass das letzte Argument in addEventListener auf true gesetzt ist. Dieses Argument heißt useCapture und ist normalerweise auf false gesetzt. Das blur-Ereignis "blubbert" nicht, wie es Ereignisse wie click tun. Das Setzen dieses Arguments auf true ermöglicht es uns, alle blur-Ereignisse zu erfassen, anstatt nur die, die direkt auf dem Element passieren, auf dem wir lauschen.
Als Nächstes möchten wir sicherstellen, dass das fokussierte Element ein Feld in einem Formular mit der Klasse .validate war. Wir können das fokussierte Element mit event.target abrufen und sein übergeordnetes Formular durch Aufrufen von event.target.form erhalten. Dann verwenden wir classList, um zu überprüfen, ob das Formular die Validierungsklasse hat oder nicht.
Wenn dies der Fall ist, können wir die Feldgültigkeit prüfen.
// Listen to all blur events
document.addEventListener('blur', function (event) {
// Only run if the field is in a form to be validated
if (!event.target.form.classList.contains('validate')) return;
// Validate the field
var error = event.target.validity;
console.log(error);
}, true);
Wenn error true ist, ist das Feld gültig. Andernfalls liegt ein Fehler vor.
Siehe den Pen Form Validation: Validate On Blur von Chris Ferdinandi (@cferdinandi) auf CodePen.
Den Fehler ermitteln
Sobald wir wissen, dass ein Fehler vorliegt, ist es hilfreich zu wissen, was der Fehler tatsächlich ist. Wir können die anderen Validity State-Eigenschaften verwenden, um diese Informationen zu erhalten.
Da wir jede Eigenschaft prüfen müssen, kann der Code dafür etwas lang werden. Richten wir dafür eine separate Funktion ein und übergeben ihr unser Feld.
// Validate the field
var hasError = function (field) {
// Get the error
};
// Listen to all blur events
document.addEventListner('blur', function (event) {
// Only run if the field is in a form to be validated
if (!event.target.form.classList.contains('validate')) return;
// Validate the field
var error = hasError(event.target);
}, true);
Es gibt einige Feldtypen, die wir ignorieren möchten: deaktivierte Felder, file- und reset-Eingaben sowie submit-Eingaben und -Buttons. Wenn ein Feld nicht eines davon ist, ermitteln wir seine Gültigkeit.
// Validate the field
var hasError = function (field) {
// Don't validate submits, buttons, file and reset inputs, and disabled fields
if (field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') return;
// Get validity
var validity = field.validity;
};
Wenn kein Fehler vorliegt, geben wir null zurück. Andernfalls prüfen wir jede der Validity State-Eigenschaften, bis wir den Fehler finden.
Wenn wir eine Übereinstimmung finden, geben wir einen String mit dem Fehler zurück. Wenn keine der Eigenschaften true ist, validity aber falsch ist, geben wir eine generische "Catch-all"-Fehlermeldung zurück (ich kann mir kein Szenario vorstellen, in dem dies vorkommt, aber es ist gut, auf Unerwartetes vorbereitet zu sein).
// Validate the field
var hasError = function (field) {
// Don't validate submits, buttons, file and reset inputs, and disabled fields
if (field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') return;
// Get validity
var validity = field.validity;
// If valid, return null
if (validity.valid) return;
// If field is required and empty
if (validity.valueMissing) return 'Please fill out this field.';
// If not the right type
if (validity.typeMismatch) return 'Please use the correct input type.';
// If too short
if (validity.tooShort) return 'Please lengthen this text.';
// If too long
if (validity.tooLong) return 'Please shorten this text.';
// If number input isn't a number
if (validity.badInput) return 'Please enter a number.';
// If a number value doesn't match the step interval
if (validity.stepMismatch) return 'Please select a valid value.';
// If a number field is over the max
if (validity.rangeOverflow) return 'Please select a smaller value.';
// If a number field is below the min
if (validity.rangeUnderflow) return 'Please select a larger value.';
// If pattern doesn't match
if (validity.patternMismatch) return 'Please match the requested format.';
// If all else fails, return a generic catchall error
return 'The value you entered for this field is invalid.';
};
Das ist ein guter Anfang, aber wir können einige zusätzliche Parsings durchführen, um einige unserer Fehler nützlicher zu machen. Für typeMismatch können wir prüfen, ob es sich um eine email oder url handeln soll und den Fehler entsprechend anpassen.
// If not the right type
if (validity.typeMismatch) {
// Email
if (field.type === 'email') return 'Please enter an email address.';
// URL
if (field.type === 'url') return 'Please enter a URL.';
}
Wenn der Feldwert zu lang oder zu kurz ist, können wir sowohl herausfinden, wie lang oder kurz er sein soll, als auch wie lang oder kurz er tatsächlich ist. Wir können diese Informationen dann in den Fehler aufnehmen.
// If too short
if (validity.tooShort) return 'Please lengthen this text to ' + field.getAttribute('minLength') + ' characters or more. You are currently using ' + field.value.length + ' characters.';
// If too long
if (validity.tooLong) return 'Please short this text to no more than ' + field.getAttribute('maxLength') + ' characters. You are currently using ' + field.value.length + ' characters.';
Wenn ein Zahlenfeld über oder unter dem zulässigen Bereich liegt, können wir diesen minimal oder maximal zulässigen Wert in unseren Fehler aufnehmen.
// If a number field is over the max
if (validity.rangeOverflow) return 'Please select a value that is no more than ' + field.getAttribute('max') + '.';
// If a number field is below the min
if (validity.rangeUnderflow) return 'Please select a value that is no less than ' + field.getAttribute('min') + '.';
Und wenn es eine pattern-Fehlübereinstimmung gibt und das Feld einen title hat, können wir diesen wie beim nativen Browserverhalten als Fehler verwenden.
// If pattern doesn't match
if (validity.patternMismatch) {
// If pattern info is included, return custom error
if (field.hasAttribute('title')) return field.getAttribute('title');
// Otherwise, generic error
return 'Please match the requested format.';
}
Hier ist der vollständige Code für unsere hasError()-Funktion.
// Validate the field
var hasError = function (field) {
// Don't validate submits, buttons, file and reset inputs, and disabled fields
if (field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') return;
// Get validity
var validity = field.validity;
// If valid, return null
if (validity.valid) return;
// If field is required and empty
if (validity.valueMissing) return 'Please fill out this field.';
// If not the right type
if (validity.typeMismatch) {
// Email
if (field.type === 'email') return 'Please enter an email address.';
// URL
if (field.type === 'url') return 'Please enter a URL.';
}
// If too short
if (validity.tooShort) return 'Please lengthen this text to ' + field.getAttribute('minLength') + ' characters or more. You are currently using ' + field.value.length + ' characters.';
// If too long
if (validity.tooLong) return 'Please shorten this text to no more than ' + field.getAttribute('maxLength') + ' characters. You are currently using ' + field.value.length + ' characters.';
// If number input isn't a number
if (validity.badInput) return 'Please enter a number.';
// If a number value doesn't match the step interval
if (validity.stepMismatch) return 'Please select a valid value.';
// If a number field is over the max
if (validity.rangeOverflow) return 'Please select a value that is no more than ' + field.getAttribute('max') + '.';
// If a number field is below the min
if (validity.rangeUnderflow) return 'Please select a value that is no less than ' + field.getAttribute('min') + '.';
// If pattern doesn't match
if (validity.patternMismatch) {
// If pattern info is included, return custom error
if (field.hasAttribute('title')) return field.getAttribute('title');
// Otherwise, generic error
return 'Please match the requested format.';
}
// If all else fails, return a generic catchall error
return 'The value you entered for this field is invalid.';
};
Probieren Sie es selbst im untenstehenden Pen aus.
Siehe den Pen Form Validation: Get the Error von Chris Ferdinandi (@cferdinandi) auf CodePen.
Fehlermeldung anzeigen
Sobald wir unseren Fehler erhalten haben, können wir ihn unter dem Feld anzeigen. Wir erstellen eine Funktion showError(), die dies übernimmt und ihr das Feld und den Fehler übergeben. Dann rufen wir sie in unserem Event-Listener auf.
// Show the error message
var showError = function (field, error) {
// Show the error message...
};
// Listen to all blur events
document.addEventListener('blur', function (event) {
// Only run if the field is in a form to be validated
if (!event.target.form.classList.contains('validate')) return;
// Validate the field
var error = hasError(event.target);
// If there's an error, show it
if (error) {
showError(event.target, error);
}
}, true);
In unserer showError-Funktion werden wir ein paar Dinge tun:
- Wir fügen dem Feld mit dem Fehler eine Klasse hinzu, damit wir es gestalten können.
- Wenn bereits eine Fehlermeldung vorhanden ist, aktualisieren wir sie mit neuem Text.
- Andernfalls erstellen wir eine Nachricht und fügen sie sofort nach dem Feld in das DOM ein.
Wir verwenden auch die Feld-ID, um eine eindeutige ID für die Nachricht zu erstellen, damit wir sie später wiederfinden können (wobei wir auf den Feldnamen zurückgreifen, falls keine ID vorhanden ist).
var showError = function (field, error) {
// Add error class to field
field.classList.add('error');
// Get field id or name
var id = field.id || field.name;
if (!id) return;
// Check if error message field already exists
// If not, create one
var message = field.form.querySelector('.error-message#error-for-' + id );
if (!message) {
message = document.createElement('div');
message.className = 'error-message';
message.id = 'error-for-' + id;
field.parentNode.insertBefore( message, field.nextSibling );
}
// Update error message
message.innerHTML = error;
// Show error message
message.style.display = 'block';
message.style.visibility = 'visible';
};
Um sicherzustellen, dass Screenreader und andere assistive Technologien wissen, dass unsere Fehlermeldung mit unserem Feld verknüpft ist, müssen wir auch die aria-describedby-Rolle hinzufügen.
var showError = function (field, error) {
// Add error class to field
field.classList.add('error');
// Get field id or name
var id = field.id || field.name;
if (!id) return;
// Check if error message field already exists
// If not, create one
var message = field.form.querySelector('.error-message#error-for-' + id );
if (!message) {
message = document.createElement('div');
message.className = 'error-message';
message.id = 'error-for-' + id;
field.parentNode.insertBefore( message, field.nextSibling );
}
// Add ARIA role to the field
field.setAttribute('aria-describedby', 'error-for-' + id);
// Update error message
message.innerHTML = error;
// Show error message
message.style.display = 'block';
message.style.visibility = 'visible';
};
Fehlermeldung gestalten
Wir können die Klassen .error und .error-message verwenden, um unser Formularfeld und die Fehlermeldung zu gestalten.
Als einfaches Beispiel möchten Sie vielleicht einen roten Rand um Felder mit einem Fehler anzeigen und die Fehlermeldung rot und kursiv gestalten.
.error {
border-color: red;
}
.error-message {
color: red;
font-style: italic;
}
Siehe den Pen Form Validation: Display the Error von Chris Ferdinandi (@cferdinandi) auf CodePen.
Fehlermeldung ausblenden
Sobald wir einen Fehler angezeigt haben, wird Ihr Besucher ihn hoffentlich beheben. Sobald das Feld gültig ist, müssen wir die Fehlermeldung entfernen. Erstellen wir eine weitere Funktion, removeError(), und übergeben ihr das Feld. Diese Funktion rufen wir ebenfalls aus dem Event-Listener auf.
// Remove the error message
var removeError = function (field) {
// Remove the error message...
};
// Listen to all blur events
document.addEventListener('blur', function (event) {
// Only run if the field is in a form to be validated
if (!event.target.form.classList.contains('validate')) return;
// Validate the field
var error = event.target.validity;
// If there's an error, show it
if (error) {
showError(event.target, error);
return;
}
// Otherwise, remove any existing error message
removeError(event.target);
}, true);
In removeError() wollen wir:
- Die Fehlerklasse von unserem Feld entfernen.
- Die
aria-describedby-Rolle vom Feld entfernen. - Alle sichtbaren Fehlermeldungen im DOM ausblenden.
Da wir mehrere Formulare auf einer Seite haben könnten und die Chance besteht, dass diese Formulare Felder mit demselben Namen oder derselben ID haben (auch wenn das ungültig ist, es passiert), beschränken wir die Suche nach der Fehlermeldung mit querySelector auf das Formular, in dem sich unser Feld befindet, anstatt auf das gesamte Dokument.
// Remove the error message
var removeError = function (field) {
// Remove error class to field
field.classList.remove('error');
// Remove ARIA role from the field
field.removeAttribute('aria-describedby');
// Get field id or name
var id = field.id || field.name;
if (!id) return;
// Check if an error message is in the DOM
var message = field.form.querySelector('.error-message#error-for-' + id + '');
if (!message) return;
// If so, hide it
message.innerHTML = '';
message.style.display = 'none';
message.style.visibility = 'hidden';
};
Siehe den Pen Form Validation: Remove the Error After It’s Fixed von Chris Ferdinandi (@cferdinandi) auf CodePen.
Wenn das Feld ein Radiobutton oder eine Checkbox ist, müssen wir ändern, wie wir unsere Fehlermeldung in das DOM einfügen.
Das Feld-Label kommt oft nach dem Feld oder umschließt es vollständig, bei diesen Arten von Eingaben. Zusätzlich wollen wir, wenn der Radiobutton Teil einer Gruppe ist, dass der Fehler nach der Gruppe und nicht nur nach dem Radiobutton erscheint.
Siehe den Pen Form Validation: Issues with Radio Buttons & Checkboxes von Chris Ferdinandi (@cferdinandi) auf CodePen.
Zuerst müssen wir unsere showError()-Methode modifizieren. Wenn der Feldtyp radio ist UND er einen name hat, wollen wir alle Radiobuttons mit demselben name (d. h. alle anderen Radiobuttons in der Gruppe) abrufen und die Variable field auf den letzten in der Gruppe zurücksetzen.
// Show the error message
var showError = function (field, error) {
// Add error class to field
field.classList.add('error');
// If the field is a radio button and part of a group, error all and get the last item in the group
if (field.type === 'radio' && field.name) {
var group = document.getElementsByName(field.name);
if (group.length > 0) {
for (var i = 0; i < group.length; i++) {
// Only check fields in current form
if (group[i].form !== field.form) continue;
group[i].classList.add('error');
}
field = group[group.length - 1];
}
}
...
};
Wenn wir unsere Nachricht in das DOM einfügen wollen, wollen wir zuerst prüfen, ob der Feldtyp radio oder checkbox ist. Wenn ja, wollen wir das Feld-Label abrufen und unsere Nachricht nach diesem einfügen, anstatt nach dem Feld selbst.
// Show the error message
var showError = function (field, error) {
...
// Check if error message field already exists
// If not, create one
var message = field.form.querySelector('.error-message#error-for-' + id );
if (!message) {
message = document.createElement('div');
message.className = 'error-message';
message.id = 'error-for-' + id;
// If the field is a radio button or checkbox, insert error after the label
var label;
if (field.type === 'radio' || field.type ==='checkbox') {
label = field.form.querySelector('label[for="' + id + '"]') || field.parentNode;
if (label) {
label.parentNode.insertBefore( message, label.nextSibling );
}
}
// Otherwise, insert it after the field
if (!label) {
field.parentNode.insertBefore( message, field.nextSibling );
}
}
...
};
Wenn wir den Fehler entfernen wollen, müssen wir ähnlich prüfen, ob das Feld ein Radiobutton ist, der Teil einer Gruppe ist, und wenn ja, den letzten Radiobutton in dieser Gruppe verwenden, um die ID unserer Fehlermeldung abzurufen.
// Remove the error message
var removeError = function (field) {
// Remove error class to field
field.classList.remove('error');
// If the field is a radio button and part of a group, remove error from all and get the last item in the group
if (field.type === 'radio' && field.name) {
var group = document.getElementsByName(field.name);
if (group.length > 0) {
for (var i = 0; i < group.length; i++) {
// Only check fields in current form
if (group[i].form !== field.form) continue;
group[i].classList.remove('error');
}
field = group[group.length - 1];
}
}
...
};
Siehe den Pen Form Validation: Fixing Radio Buttons & Checkboxes von Chris Ferdinandi (@cferdinandi) auf CodePen.
Alle Felder beim Absenden prüfen
Wenn ein Besucher unser Formular absendet, sollten wir zuerst jedes Feld im Formular validieren und Fehlermeldungen für alle ungültigen Felder anzeigen. Wir sollten auch das erste Feld mit einem Fehler in den Fokus bringen, damit der Besucher sofort handeln kann, um es zu korrigieren.
Dies tun wir, indem wir einen Listener für das submit-Ereignis hinzufügen.
// Check all fields on submit
document.addEventListener('submit', function (event) {
// Validate all fields...
}, false);
Wenn das Formular die Klasse .validate hat, rufen wir jedes Feld ab, durchlaufen es und prüfen auf Fehler. Wir speichern das erste ungültige Feld, das wir finden, in einer Variablen und bringen es in den Fokus, wenn wir fertig sind. Wenn keine Fehler gefunden werden, kann das Formular normal abgeschickt werden.
// Check all fields on submit
document.addEventListener('submit', function (event) {
// Only run on forms flagged for validation
if (!event.target.classList.contains('validate')) return;
// Get all of the form elements
var fields = event.target.elements;
// Validate each field
// Store the first field with an error to a variable so we can bring it into focus later
var error, hasErrors;
for (var i = 0; i < fields.length; i++) {
error = hasError(fields[i]);
if (error) {
showError(fields[i], error);
if (!hasErrors) {
hasErrors = fields[i];
}
}
}
// If there are errrors, don't submit form and focus on first element with error
if (hasErrors) {
event.preventDefault();
hasErrors.focus();
}
// Otherwise, let the form submit normally
// You could also bolt in an Ajax form submit process here
}, false);
Siehe den Pen Form Validation: Validate on Submit von Chris Ferdinandi (@cferdinandi) auf CodePen.
Alles zusammenfügen
Unser fertiges Skript wiegt nur 6 KB (2,7 KB minimiert). Sie können eine Plugin-Version auf GitHub herunterladen.
Es funktioniert in allen modernen Browsern und bietet Unterstützung für IE ab IE10. Es gibt jedoch einige Browser-Eigenheiten...
- Da wir keine schönen Dinge haben können, unterstützt nicht jeder Browser jede Validity State-Eigenschaft.
- Internet Explorer ist natürlich der Hauptsünder, obwohl Edge die Unterstützung für
tooLongfehlt, obwohl IE10+ sie unterstützt. Wer hätte das gedacht.
Hier ist die gute Nachricht: Mit einem leichten Polyfill (5 KB, 2,7 KB minimiert) können wir die Browserunterstützung bis zurück zu IE9 erweitern und fehlende Eigenschaften zu teilweise unterstützenden Browsern hinzufügen, ohne unseren Kerncode anfassen zu müssen.
Es gibt *eine* Ausnahme zur IE9-Unterstützung: Radiobuttons. IE9 unterstützt keine CSS3-Selektoren (wie [name="' + field.name + '"]). Wir verwenden das, um sicherzustellen, dass mindestens ein Radiobutton innerhalb einer Gruppe ausgewählt wurde. IE9 wird immer einen Fehler zurückgeben.
Ich werde Ihnen im nächsten Artikel zeigen, wie Sie diesen Polyfill erstellen.
Artikelserie
- Constraint-Validierung in HTML
- Die Constraint Validation API in JavaScript (Sie sind hier!)
- Ein Validity State API Polyfill
- Validierung des MailChimp-Anmeldeformulars
Fantastischer Artikel! Besonders da ich gerade die Anwendungsseite für mein Unternehmen überarbeite und die aktive Formularvalidierung etwas ist, das die Vorgesetzten ausdrücklich verlangt haben.
Eine Sache jedoch: Wenn man mit der Maus über den Fehlertext in den E-Mail- oder URL-Feldern fährt, wird ein Alt-Text angezeigt, der besagt, was der Browser mit dem aktuellen Text falsch zu machen scheint (z. B. "diesem fehlt eine .com" oder "der Text nach @ ist ungültig").
Nur dass der Text immer fehlerhaft zu sein scheint. Er fordert den Benutzer immer wieder auf, etwas zu korrigieren, das nicht falsch ist, was jeden verwirren wird, der das Pech hat, für eine Sekunde darüber zu schweben.
Haben Sie eine Idee, wie man Alt-Texte in diesen Fällen deaktivieren kann, oder gibt es einen Grund, warum er diese falschen Meldungen geben könnte?
Das ist ziemlich ärgerlich, nicht wahr? Das scheint mir ein schlechtes Spec-Design zu sein, aber wir könnten auch unseren Musterfehler umschreiben, um etwas wie
Ihre URL muss eine TLD enthalten (z. B. .com)zu sagen.Immer noch wahrscheinlich etwas verwirrend.
Ein anderer Ansatz, den wir verwenden *könnten*, obwohl ich ihn nicht unbedingt empfehlen würde, ist die programmatische Umwandlung aller
title-Attribute in Datenattribute. Etwas wie das hier:Dann werden wir in unserem Validierungsskript anstelle des Abrufs des
titledasdata-titleverwenden.Sie fragen sich vielleicht, warum ich
data-titlenicht gleich von Anfang an verwendet habe, anstatt es mit JS zu ersetzen. Wenn unser JavaScript fehlschlägt und die native HTML-Constraint-Validierung die Lücke füllt, wollen wir unsertitle-Attribut immer noch dort haben.Wow! So viele gute Infos! Danke fürs Zusammenstellen!
Gern geschehen!
Ich bin neugierig, wie das gut mit Fehlern zusammenarbeitet, die nur serverseitig geprüft werden können, wie eine eindeutige E-Mail für die Registrierung oder eine ungültige Postleitzahl. Würden Sie diese Inline anzeigen und hoffen, dass der Benutzer sie vor dem ersten "Blur" behebt, oder alles in einer Benachrichtigungsbox über dem Formular bündeln?
Zweitens habe ich das Gefühl, dass dies großartig für weniger komplexe Formulare ist, aber ich brauche öfter eine Validierungsbibliothek, wenn Dinge von anderen Feldern abhängen, wie "dies ist erforderlich, wenn diese Checkbox markiert ist" oder "dieses Datum muss vor jenem liegen". Ich habe zuvor Nette Forms erfolgreich mit dem dazugehörigen Nette-Forms.js verwendet. Es ist auch recht klein im Frontend und unabhängig von jQuery und löst dieses Problem mit Abhängigkeiten zwischen Feldern. Da ich nicht immer PHP verwende, bin ich neugierig auf Alternativen.
Ich denke, es ergänzt diese Arten von Fehlern. In einer perfekten Welt könnten Sie beim Verlassen eines Feldes eine Ajax-Anfrage an den Server senden, um sie zu prüfen, und bei Bedarf einen Fehler anzeigen.
Alternative Ansätze
Die letztere Option wird jedoch wahrscheinlich verwirrend, wenn jemand die Korrektur vornimmt, aber der Fehler nicht verschwindet.
Für komplexere Dinge, wie Sie sie beschrieben haben, könnten Sie Ihre eigene kleine Enhancer-Funktion schreiben, um damit umzugehen (hier ist zum Beispiel wie man die Gültigkeit eines Datums mit Vanilla JavaScript prüft, einschließlich der Berücksichtigung von Schaltjahren). Oder Sie wären zu 100 % berechtigt, eine robustere Bibliothek zu verwenden.
Vielen Dank Chris. Wirklich nützlicher Artikel
Danke Louis!
Wenn ich faul bin und nur die Standardfehlermeldungen anzeigen möchte, aber beim Verlassen des Feldes statt beim Absenden, wie mache ich das am einfachsten?
validate.init({selector: 'form'}), um es auf alle Formulare anzuwenden.Wenn Sie die nativen Fehlermeldungen mit nativem Styling anzeigen möchten, nun ja... es gibt die Methode
reportValidity(), aber sie bringt das Feld wieder in den Fokus und erzeugt diese Art von "Hotel California"-Hölle, die Sie auf jedem Feld mit einem Fehler gefangen hält... also ist es keine gute Wahl.Im Code-Snippet für die Radiobuttons in der
showError-Funktion, anstatt zu verwendenkönnten Sie wahrscheinlich verwenden
und dann die
if-Bedingung loswerdenin der for-Schleife.
Ich habe das ursprünglich verwendet, aber als ich den Polyfill im nächsten Artikel verwendet habe, um die Unterstützung bis IE9 zurückzuverfolgen, schlug er fehl. Ich bin zu
getElementsByName+ der Form-Prüfung für bessere Unterstützung gewechselt.Hmm?! Sehr seltsam! Soweit ich weiß, unterstützt IE9 querySelectorAll.
Das tut es, genauso wie IE8. Ich bin sicher, es ist etwas Einfaches und Dummes, aber ich habe entschieden, dass eine zusätzliche Codezeile eine bessere Wahl war als die Fehlersuche unter Zeitdruck. =)
Wie verwende ich es in Verbindung mit Ajax? Vielen Dank im Voraus.
Hallo Dimitrian! Ajax-Formularübermittlung variiert stark von Formular zu Formular, abhängig davon, wie der Server, der die Formulardaten empfängt, eingerichtet ist. Als Beispiel sehen Sie jedoch Teil 4, wo ich beschreibe, wie man das MailChimp-Anmeldeformular mit Ajax übermittelt.
Ich entschuldige mich, falls dies bereits behandelt wurde, aber gibt es etwas Stärkeres zur Validierung einer E-Mail-Adresse, um sicherzustellen, dass die E-Mail-Adresse tatsächlich existiert?
Ich habe ein Formular, in dem ich ein Honey-Pot eingebaut habe, um Bots davon abzuhalten, mich per E-Mail zu kontaktieren, aber überraschenderweise erhalte ich viele E-Mails von Menschen, die ungültige E-Mail-Adressen verwenden.
Ich liebe diesen Beitrag über Formularvalidierungen! Danke!
Ich finde das eigentlich gar nicht so überraschend (wahrscheinlich, weil ich es auch schon erlebt habe).
Dafür gibt es ein paar Optionen:
Wenn ich Sie wäre, würde ich entweder Option 1 wählen oder das als Teil des Geschäfts betrachten. =(
Ich schätze die Aufschlüsselung der Optionen. Ich werde mich damit beschäftigen und sehen, was ich herausfinden kann. Ich sehe, wie schwierig es wäre, etwas (eine Bibliothek oder ein Plugin) Millionen von E-Mail-Adressen durchsuchen zu lassen, nur um zu sehen, ob die verwendete echt ist. Es gibt jedoch für fast alles heutzutage eine App, also dachte ich, es wäre nicht außerhalb des Bereichs des Möglichen.