Introducere în Formulare în Angular 4 Scrierea validatorilor de formular personalizat

Aceasta este a treia parte a seriei despre crearea formelor în Angular. În primele două tutoriale am folosit abordarea bazată pe șablon și modelul Angular pentru a crea formulare. Cu toate acestea, în timp ce am detaliat ambele abordări, a existat ceva pe care nu l-am acoperit - funcții personalizate de validare. Acest tutorial va acoperi tot ce trebuie să știți despre scrierea validatorilor personalizați care să corespundă cerințelor dvs..

Cerințe preliminare

Nu trebuie să fi urmat partea a doua sau două din această serie pentru partea a treia pentru a avea sens. Cu toate acestea, dacă sunteți complet nou în formularele Angular, trebuie să vă îndreptați spre primul tutorial al acestei serii și să începeți de acolo. 

În caz contrar, apucați o copie a acestui cod de la repo GitHub și folosiți-o ca punct de plecare.  

Validatori încorporați

Angular nu se mândrește cu o imensă bibliotecă de validare încorporată. Din Angular 4, avem următoarele validatoare populare în Angular:

  • necesar
  • Minlength
  • lungime maxima
  • model

Există de fapt și câteva altele și puteți vedea lista completă în documentele angulare. 

Putem folosi validatoarele integrate de mai sus în două moduri:

1. Ca directive în formule bazate pe șablon.

2. Ca validatori în interiorul FormControl constructor în forme bazate pe model.

nume = nou FormControl (", Validators.required) 

Dacă sintaxa de mai sus nu are sens, urmați tutorialele mele anterioare privind construirea unui formular de înscriere utilizând o abordare bazată pe șablon sau o abordare bazată pe model și apoi abandonarea!

Validatorii de formate integrate acoperă cu greu toate cazurile de validare care ar putea fi necesare într-o aplicație din lumea reală. De exemplu, este posibil ca un formular de înscriere să verifice dacă valorile câmpurilor de parolă și de confirmare a parolei sunt egale și să afișeze un mesaj de eroare dacă nu se potrivesc. Un validator care conține liste negre de e-mailuri dintr-un anumit domeniu este un alt exemplu obișnuit. 

Iată un fapt: Formularele bazate pe șabloane sunt doar formele bazate pe model sub ele. Într-o formă bazată pe șablon, lăsăm șablonului să aibă grijă de crearea modelului pentru noi. Întrebarea evidentă este acum cum atașați un validator unui formular?

Validatorii sunt doar funcții. Într-o formă bazată pe model, atașarea validatorilor la FormControl este simplă. Într-o formă bazată pe șablon, totuși, este ceva mai mult de făcut. În plus față de funcția validator, va trebui să scrieți o directivă pentru validator și să creați instanțe ale directivei în șablon.

Scufundări în detalii

Deși acest lucru a fost deja acoperit, vom trece printr-o recapitulare rapidă a codului pentru formularul de înscriere. Mai întâi, iată abordarea reactivă.

app / înscriere / formularul de înscriere la form.component.ts

 // Folosiți formbuilder-ul pentru a construi modelul Formularul this.signupForm = this.fb.group (email: [", [Validators.required, Validators.pattern ('[a-z0-9 ._% + -] + [a-z0-9 .-] + \. [az] 2,3 $ ')]], parola: this.fb.group (pwd: [", Validators.required, Validators.minLength )]], confirmPwd: [", Validatori.required, Validators.minLength (8)]], validator: PasswordMatch), gen: [" Validators.required]

FormBuilder este un sintaxă de zahăr care creează FormGroup și FormControl instanțe. A FormControl urmărește valoarea și starea de validare a unui element de formă individual. A FormGroup, pe de altă parte, cuprinde un grup de FormControl instanțe și urmărește valoarea și valabilitatea întregului grup.

Iată structura pe care am urmat-o:

FormGroup -> 'signupForm' FormControl -> 'email' FormGroup -> 'parola' FormControl -> 'pwd' FormControl - 

În funcție de cerințe, putem atașa un validator la un FormControl sau a FormGroup. Un validator al listei negre de e-mail ar necesita ca acesta să fie atașat la FormControl exemplu de e-mail. 

Cu toate acestea, pentru validări mai complexe în cazul în care câmpurile de control multiple trebuie comparate și validate, este o idee mai bună să adăugați logica de validare părintelui FormGroup. După cum puteți vedea, parola are o FormGroup de-al ei, și acest lucru ne face ușor pentru a scrie validatori care verifică egalitatea de PWD și confirmPwd.

Pentru formularul condus de șablon, toată logica merge în șablonul HTML, și aici este un exemplu:

app / înscriere / formularul de înscriere la form.component.html

...

ngModel creează un exemplu de FormControl și o leagă de un element de control al formei. asemănător, ngModelGroup creează și leagă a FormGroup exemplu unui element DOM. Aceștia împart aceeași structură de domeniu model discutată mai sus. 

De asemenea, este interesant de menționat acest lucru FormControl, FormGroup, și FormArray extindeți AbstractControl clasă. Ce înseamnă acest lucru este faptul că AbstractControl clasa este responsabilă pentru urmărirea valorilor obiectelor de formă, validarea acestora și alimentarea altor lucruri, cum ar fi metodele clare, murdare și atinse. 

Acum, că suntem familiarizați cu ambele tehnici de formular, să scriem primul validator personalizat.

Funcția de validare personalizată pentru formularele cu funcție de model

Validatorii sunt funcții care iau a FormControl/FormGroup instanță ca intrare și returnare fie nul sau un obiect de eroare. nul este returnat atunci când validarea este reușită și, dacă nu, obiectul de eroare este aruncat. Iată o versiune foarte fundamentală a unei funcții de validare. 

app / parola-match.ts

import FormGroup din '@ unghiular / formulare'; funcția de export passwordMatch (control: FormGroup): [cheie: șir]: boolean 

Am declarat o funcție care acceptă o instanță FormGroup ca intrare. Returnează un obiect cu o cheie de tip șir și o valoare adevărată / falsă. Aceasta este pentru a putea returna un obiect de eroare al formularului de mai jos:

mismatch: true

Apoi, trebuie să obținem valoarea PWD și confirmPwd FormControl instanțe. Voi folosi control.get () pentru a le aduce valorile. 

funcția de export passwordMatch (control: FormGroup): [cheie: string]: boolean // Grab pwd și confirmPwd folosind control.get const pwd = control.get ('pwd'); const confir confirmPwd = control.get ('confirmPwd');  

Acum trebuie să facem comparația și apoi să întoarcem fie un obiect nul sau un obiect de eroare.

app / parola-match.ts

import AbstractControl din '@ unghiular / formulare'; funcția de export passwordMatch (control: AbstractControl): [cheie: șir]: boolean // Grab pwd și confirmPwd folosind control.get const pwd = control.get ('pwd'); const confir confirmPwd = control.get ('confirmPwd'); // Dacă obiectele FormControl nu există, întoarceți null dacă (! Pwd ||! ConfirmPwd) întoarce null; // Dacă sunt într-adevăr egale, întoarceți null dacă (pwd.value === confirmPwd.value) return null;  // Înapoi return false return mismatch: true;  

De ce am înlocuit-o FormGroup cu AbstractControl? După cum știți, AbstractControl este mama tuturor claselor Form *, și vă oferă mai mult control asupra obiectelor de control al formei. Are avantajul că face codul nostru de validare mai consistent.

Importați passwordMatch funcția în SignupForm și declarați-l ca validator al parolei FormGroup instanță.

app / parola-match.ts

importați passwordMatch de la "./... / password-match"; ... clasa de export SignupFormComponent implementează OnInit ngOnInit () // Utilizați formbuilder pentru a construi modelul This.signupForm = this.fb.group (... password: (validators.required, Validators.minLength (8)]], validator: passwordMatch (pwd: ), ...) 

Afișarea erorilor

Dacă ai făcut totul bine, password.errors? .mismatch va fi adevărat ori de câte ori valorile ambelor câmpuri nu se potrivesc.

parola.error ?.mismatch json

Deși există modalități alternative de a afișa erori, voi folosi ngIf pentru a determina dacă un mesaj de eroare ar trebui afișat sau nu.

În primul rând, o să folosesc ngIf pentru a vedea dacă parola este nevalidă. 

  

Folosim password.touched pentru a vă asigura că utilizatorul nu este întâmpinat cu erori chiar înainte de apăsarea unei taste.

Apoi, voi folosi sintaxa ngIf = "expresie; apoi o altceva" pentru a afișa eroarea corectă.

app / înscriere / formularul de înscriere la form.component.html

    Parola nu se potriveste   Parola trebuie să aibă mai mult de 8 caractere 

Acolo îl aveți, un model de lucru al validatorului care verifică egalitatea parolei.

Demo pentru Validatorii personalizați în Formulare conduse de modele

Ghid de validare personalizată pentru formularele cu șablon

Vom folosi aceeași funcție de validare pe care am creat-o mai devreme pentru modelul bazat pe model. Cu toate acestea, nu avem acces direct la instanțe FormControl/FormGroup într-o formă bazată pe șablon. Iată câteva lucruri pe care trebuie să le faceți pentru a face munca de validare:

  1. Creeaza o PasswordMatchDirective care servește ca un înveliș în jurul valorii de passwordMatch funcția validator. Vom înregistra directiva ca validator folosind NG_VALIDATORS furnizor. Mai multe despre asta mai târziu.
  2. Atașați directiva la controlul formei șablonului. 

Să scriem mai întâi directiva. Iată ce arată o directivă în Angular:

app / parola-match.ts

import AbstractControl din '@ unghiular / formulare'; funcția de export passwordMatch (control: AbstractControl): [cheie: șir]: boolean // Grab pwd și confirmPwd folosind control.get const pwd = control.get ('pwd'); const confir confirmPwd = control.get ('confirmPwd'); // Dacă obiectele FormControl nu există, întoarceți null dacă (! Pwd ||! ConfirmPwd) întoarce null; // Dacă sunt într-adevăr egale, întoarceți null dacă (pwd.value === confirmPwd.value) return null;  // Înapoi return false return mismatch: true;  // PasswordMatchDirective @Directive (selector: ", furnizori: []) clasa de export PasswordMatchDirective 

@Directivă decorator este folosit pentru a marca clasa ca o directivă unghiulară. Acceptă un obiect ca argument care specifică metadatele de configurare a directivei, cum ar fi selectorii pentru care directiva ar trebui să fie atașată și lista furnizorilor care urmează să fie injectați etc. Să completăm metadatele de directivă:

app / parola-match.ts

@Directive (selector: '[passwordMatch] [ngModelGroup]', // 1 furnizori: [// 2 furniza: NG_VALIDATORS, useValue: passwordMatch, multi: true]
  1. Directiva este acum atașată tuturor controalelor de intrare care au atributele ngModelGroup și passwordMatch
  2. Extindeți validatorii încorporați utilizând NG_VALIDATORS furnizor. Așa cum am menționat anterior, NG_VALIDATORS este un furnizor care are o colecție extensibilă de validatori. passwordMatch funcția pe care am creat-o mai devreme este declarată ca o dependență. multi: adevărat setează acest furnizor ca furnizor multiplu. Ce înseamnă acest lucru este că vom adăuga la colecția existentă de validatori furnizată de NG_VALIDATORS.

Acum, adăugați directiva la matricea declarațiilor în ngModule.

app / app.module.ts

... import PasswordMatchDirective din "./password-match"; @NgModule (declarații: [AppComponent, SignupFormComponent, PasswordMatchDirective], import: [BrowserModule, FormsModule], furnizori: [], bootstrap: [AppComponent]) 

Afișarea mesajelor de eroare

Pentru a afișa mesajele de eroare de validare, voi folosi același șablon pe care l-am creat pentru formularele bazate pe modele.

 
Parola nu se potriveste Parola trebuie să aibă mai mult de 8 caractere

Concluzie

În acest tutorial, am aflat despre crearea validatorilor angulari personalizați pentru formularele în Angular. 

Validatorii sunt funcții care returnează nul sau un obiect de eroare. În formele bazate pe modele, trebuie să atașăm validatorul la o instanță FormControl / FormGroup și asta este. Procedura a fost un pic mai complexă într-o formă bazată pe șablon deoarece am avut nevoie să creăm o direcție pe partea de sus a funcției validator. 

Dacă sunteți interesat să continuați să aflați mai multe despre JavaScript, nu uitați să aflați ce avem în Envato Market.

Sper că te-ai bucurat de această serie pe Formulare în Angular. Mi-ar plăcea să vă aud gândurile. Trimiteți-le prin comentarii. 

Cod