Validieren von Formularen anhand von Standards mit der Validierungs-API

Zu einer Zeit mochten fast alle Angular 2+, es ist ein gut gestaltetes Framework, das sich in Bezug auf die technische Leistung von den anderen beliebten Front-End-Frameworks abhebt. Aber er hatte auch sehr seltsame Mängel. Eine davon ist die Unmöglichkeit, die Validierung oder Revalidierung des Formulars manuell aufzurufen, was zumindest bis zur 8. Version beobachtet wurde. Dies bedeutet nicht, dass sie sehr an Reaktivität interessiert sind, aber in diesem Subsystem scheinen einige reaktive Überlegungen Entwickler dazu veranlasst zu haben, die Validierung nur durch Bindung zu implementieren, was Anwendungsentwickler dazu zwingt, sich Krücken zuzuwenden, wie den Status "unberührt" für Felder festzulegen und das Schreiben komplexer Validatoren im Allgemeinen mit Advanced zu erschweren Logik und Beteiligung mehrerer Bereiche gleichzeitig.Die Erfahrung im Umgang mit dem Angular-Validator und einigen anderen Funktionen des Frameworks hat meinen Eindruck bestärkt, wie elegant und einfach es danach war, die HTML5-API für die Formularvalidierung zu verwenden, die in jedem modernen Browser „nur funktioniert“, auch ohne die Verwendung von Frameworks und Bibliotheken.



Elementattribute sind die Basis für Validatoren. Mithilfe von Attributen können wir sofort die folgenden Einschränkungen festlegen:

Erforderlich - Das Feld ist erforderlich, d. H. erfordert das Ausfüllen des

Min- Max- Schritts - die minimal und maximal zulässigen Werte sowie den Schritt des Änderns der

Min- und Max-Länge - Begrenzer für die Anzahl der zulässigen Eingabezeichen -

Muster - regulärer Ausdruck

Es scheint nicht viel zu sein, aber das Muster bietet uns ziemlich viele Möglichkeiten, Werte zu überprüfen. Regelmäßige Muster können leicht gegoogelt werden So können Sie Telefonnummern, E-Mail-Adressen, URLs und vieles mehr sofort überprüfen.

Diese Attribute sind auf Formularelementen angeordnet und ermöglichen nicht automatisch, dass die Schaltfläche von demselben Formular aus ausgelöst wird, das Übermittlungswerte an den Server ausführt, obwohl ein solcher Fall heutzutage für viele anachronistisch erscheint. Das ist aber kein Problem, denn Mit clientseitigem JavaScript können wir alle diese Validatoren auf dieselbe oder sogar noch bessere Weise verwenden. Daher verwenden wir nicht den Eingabetyp = E-Mail, sondern versuchen, ein eigenes Feld zu erstellen, in dem die Eingabe auf Übereinstimmung mit den Regeln zum Generieren von E-Mail-Adressen überprüft wird. Machen wir ein einfaches Formular:

<form name="myform" id="myform">
   <input type="text" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" placeholder="email here"/>
   <input type="submit">
</form>


Der Validator funktioniert sofort und gibt beim Versuch, die Taste zu drücken, eine Warnung in der Sprache des Gebietsschemas des Browsers aus.







Dementsprechend führt die Eingabe von mail@example.com zu einer erfolgreichen Formularübermittlung.

Um Ihr Verhalten zu entwickeln, müssen Sie auf die Formularinstanz zugreifen. Dies kann über das globale Dokument nach Name, Index (ID) oder Ordnungszahl ab Null erfolgen.

<script type="module">
   document.forms.myform.onsubmit = (event) => {
       console.log('validate');
       return false;
   };
</script>


oder indem Sie einen Selektor mit einer der Methoden wie document.getElementById () oder document.querySelector () verwenden,

um die Ergebnisse zu überprüfen, führen Sie http-server aus

npx http-server


Nachdem der Befehl ausgeführt wurde, können Sie 127.0.0.1 : 8080 / oder die Adresse, die er Ihnen in die Konsole im Browser schreibt, öffnen und die Ergebnisse debuggen.



Ersetzen wir das Senden durch eine reguläre Schaltfläche und rufen die Formularüberprüfung manuell auf, wobei wir das Beispiel geringfügig ändern.

<form id="myform" action="#">
   <input type="text" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="email here" />
   <input type="button" name="subm" value="OK" />
</form>

<script type="module">;
   myform.subm.onclick = (event) => {
       console.log(form.checkValidity());
       return false;
   };
</script>


In diesem Beispiel können Sie sehen, dass das Zuordnen von Formularobjekten anhand ihrer ID und ihres Namens für untergeordnete Elemente in Bezug auf das Formular funktioniert, was sehr ordentlich aussieht. Jetzt druckt unser Code den Gültigkeitsstatus des Formulars auf die Konsole.

Das Vorhandensein von Methoden zum manuellen Starten der Validierung bedeutet nicht, dass sie nicht ausgeführt werden können, ohne sie aufzurufen.

Die Ergebnisse von Eingaben und anderen Änderungen am Formular spiegeln sich sofort in seinem Zustand wider, der sich im Vorhandensein von Pseudoklassen der gültigen und ungültigen Stile manifestiert . Wenn Sie eine Farbhervorhebung hinzufügen, können Sie sofort sehen, wie die Validierung funktioniert.

<style>
  :valid {
       border: 1px solid green;
   }
  :invalid {
       border: 1px solid red;
   }
</style>








Um zu verhindern, dass das Formular die Augen mit Rot stört, bevor der Benutzer versucht hat, etwas einzugeben, können Sie einen Life-Hack mit einem Platzhalter verwenden:

<style>
   input:valid {
       border: 1px solid green;
   }
   input:not(:placeholder-shown):invalid {
       border: 1px solid red;
   }
</style>


Externe Handler für Validierungsereignisse können an Formularelementen aufgehängt werden.

<script type="module">
   myform.email.oninvalid = (event) => {
       alert('Wrong email !!11');
   };
   myform.subm.onclick = (event) => {
       console.log(form.checkValidity());
       return false;
   };
</script>


In diesem Fall wird der Mechanismus der Hooks nach Ereignisname verwendet. Wenn ein Element vom Element unterstützt wird, können wir durch Zuweisen einer Funktion mit dem Namen + <Ereignisname> sicher sein, dass es beim Auslösen aufgerufen wird.



Und ein weiterer wunderbarer Punkt hier ist, dass sie nicht mehr bei der Eingabe von Daten aufgerufen werden, sondern nur, wenn die Validierung programmgesteuert ruckelt, d. H. Aufruf der checkValidity () -Methode.



Dementsprechend können wir mit diesem Verhalten umgehen:

myform.subm.onclick = (event) => {
   if (myform.checkValidity()) {
       alert('Valid !');
   } else {
       alert('Invalid !')
   }
   return false;
};


Im wirklichen Leben müssen wir möglicherweise auch event.preventDefault () aufrufen, wenn die Validierung den Formularübermittlungsvorgang nicht abbricht .



Bei checkValidity () handelt es sich um eine analoge reportValidity () , die das Ergebnis zurückgibt, ohne eine erneute Validierung zu verursachen.



Woher weißt du, welches Feld falsch ist?



Jedes Formulareingabeelement hat die Eigenschaft .validity sowie die Möglichkeit, Validierungsmethoden aufzurufen. Die Eigenschaft hat die folgende Struktur:



ValueState: {

valid - allgemeines Zeichen für die Richtigkeit des

WertesMissing - der Wert ist erforderlich, aber nicht gesetzt

typeMismatch - der falsche

Werttyp wurde eingegeben patternMismatch - eingeführt nicht übereinstimmender Wert

tooLong - Wert größer als maxlength

tooShort - Wert kleiner als minlength

rangeUnderflow - Wert kleiner als min

rangeOverflow - Wert größer als max

stepMismatch - Wert stimmt nicht mit dem Schritt

überein badInput - Eingabe kann nicht zum Wert

customError gezwungen werden - beliebiger Fehler

}



Grundsätzlich, wie wir sehen können, Fehlereigenschaften, die Standardvalidierungsattributen entsprechen, während .customError unser Headroom für Erweiterungen ist. Durch

Aufrufen der Methode .setCustomValidity () mit einer Fehlerzeichenfolge als Argument können wir das Formularelement als ungültig markieren. Sie können den Fehlertext auch über die Eigenschaft .validationMessage festlegen oder abrufen...

Um keine Browser-Validierungen festzulegen , können Sie die .willValidate- Eigenschaft verwenden , die angibt, ob Standardvalidierungen für das Feld aufgerufen werden.

Durch Übergeben einer leeren Zeichenfolge als Argument an .setCustomValidity () können wir den Status auf gültig zurücksetzen .

Fügen wir Unterstützung für unser eigenes my-pattern- Attribut hinzu , das den Wert aus Gründen der Klarheit auf die gleiche Weise mit einem regulären Ausdruck vergleicht.

Im Fehlerfall wird die Meldung zusätzlich zu der im Browser angegebenen Meldung neben dem Feld angezeigt. Die

Überprüfung wird ausgelöst, wenn sich der Wert unseres alternativen Felds ändert und die Taste gedrückt wird.

<form id="myform" action="#">
   <div>
       <input type="text" name="email" id="email" value="" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="email here" />
       <span class="msg"></span>
   </div>
   <div>
       <input type="text" name="customInput" id="customInput" my-pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="text here" />
       <span class="msg"></span>
   </div>
   <button type="submit" name="subm" value="OK">OK</button>
</form>
<style>
   input:valid {
       border: 1px solid green;
   }
   input:not(:placeholder-shown):invalid {
       border: 1px solid red;
   }
</style>
<script type="module">
   myform.customInput.oninvalid = (event) => {
       let el = event.target;
       let msg = el.parentElement.querySelector('.msg');
       msg.innerText = el.validationMessage;
       console.log('oninvalid, id: ', el.id);
   };
   myform.customInput.oninput = (event) => {
       let el = event.currentTarget;
       validateWithMyPattern(el);
       markValidity(el);
   };
   function markValidity(el) {
       el.checkValidity();
       let msg = el.parentElement.querySelector('.msg');
       if (el.validity.valid) {
           msg.innerText = '';
       } else {
           msg.innerText = el.validationMessage;
       }
   }
   function validateWithMyPattern(field) {
       if (field.value) {
           if (field.hasAttribute('my-pattern') &&
               field.value.match(field.getAttribute('my-pattern'))) {
               field.setCustomValidity('');
           } else {
               field.setCustomValidity('My pattern error');
           }
       }
   }
   myform.subm.onclick = (event) => {
       for (let formEl of myform.querySelectorAll('input')) {
           validateWithMyPattern(formEl);
           markValidity(formEl);
       }
       if (myform.reportValidity()) {
           alert('Valid !');
       } else {
           alert('Invalid !')
       }
       return false;
   };
</script>


Jetzt haben wir zwei ähnliche Felder, die den Wert mit einem Standardvalidator überprüfen, und eines, das wir selbst geschrieben haben.







Die Möglichkeiten scheinen nicht reich zu sein, aber mit ihrer Hilfe können Sie alle Validierungen implementieren, inkl. Gruppen von Feldern, ohne über technische Einschränkungen wie bei gängigen Frameworks zu stolpern.



Von den Einschränkungen der Validierungs-API erinnere ich mich nur an die anfängliche Ungültigmachung von Feldern. Zusätzlich zum Trick mit unberührten Platzhaltern oder Sonderzuständen können Sie die gesamte Validierung programmgesteuert für die Eingabe durchführen und Ereignisse senden, indem Sie Ihre eigenen Validatoren mit den Standard-Validatoren kombinieren.

Bei der Lösung meiner Probleme musste ich eine eigene Komponente erstellen, die gleichzeitig die Aufgaben des Formulars ausführt, um meine eigenen Eingabeelemente zu unterstützen. Auf diese Weise können Sie ein anderes Validierungs- und Benachrichtigungsverhalten festlegen und alle Validatoren aufhängen und die standardisierte Validierungs-API verwenden. Sie können es hier sehen: https://bitbucket.org/techminded/skinny-widgets/src/master/src/form/

und den Beispielcode aus diesem Artikel finden Sie hier:

https://bitbucket.org/techminded/myform /.



All Articles