您好,登錄后才能下訂單哦!
我們會在本文中探索 Angular 2 內建的自定義驗證。
# 介紹
Angular 2 原生就支持一些有用的驗證器:
我們會基于下面的接口創建一個表單來獲取用戶信息。
// user.interface.ts export interface User { username: string; // required, must be 5-8 characters email: string; // required, must be valid email format password: string; // required, value must be equal to confirm password. confirmPassword: string; // required, value must be equal to password. }
需求
僅在字段數據不正確或提交表單的時候,為每個字段 顯示錯誤消息 。
UI 展示:
# App 配置
這是我們的文件結構:
|- app/ |- app.component.html |- app.component.ts |- app.module.ts |- equal-validator.directive.ts |- main.ts |- user.interface.ts |- index.html |- styles.css |- tsconfig.json
為了使用新的表單模塊,我們需要用 npm install @ angular/forms 指令調用 npm 包,并在應用程序模塊中導入最新的表單模塊。
$ npm install @angular/forms --save
下面是我們應用程序的 app.module.ts 模塊:
// app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, FormsModule ], // import forms module here declarations: [ AppComponent ], bootstrap: [ AppComponent ], }) export class AppModule { }
# App 組件
讓我們繼續創建 App 組件。
// app.component.ts import { Component, OnInit } from '@angular/core'; import { User } from './user.interface'; @Component({ moduleId: module.id, selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.css'] }) export class AppComponent implements OnInit { public user: User; ngOnInit() { // initialize model here this.user = { username: '', email: '', password: '', confirmPassword: '' } } save(model: User, isValid: boolean) { // 調用API保存customer console.log(model, isValid); } }
# HTML 視圖
這是我們的 HTML 視圖的樣子。
<!-- app.component.html --> <div> <h2>Add user</h2> <form #f="ngForm" novalidate (ngSubmit)="save(f.value, f.valid)"> <!-- 我們將把驗證的字段放在這里 --> <button type="submit" [disabled]="!myForm.valid">Submit</button> </form> </div>
現在來一個個添加控件。
用戶名
需求: 必填,長度在 5-8 個字符之間
<!-- app.component.html --> ... <div> <label>Username</label> <input type="text" name="username" [ngModel]="user.username" required minlength="5" maxlength="8" #username="ngModel"> <small [hidden]="username.valid || (username.pristine && !f.submitted)"> Username is required (minimum 5 characters). </small> </div> <pre *ngIf="username.errors">{{ username.errors | json }}</pre> ...
required、minlength、maxlength 都是內置的驗證器,所以很容易使用。
我們只會在用戶名無效、獲得焦點和提交表單的情況下顯示錯誤消息。最后一條的 pre 標簽在開發過程中對調試很有用。它會顯示字段的所有驗證錯誤。
電子郵件地址
需求: 必填,必須是有效的電子郵件地址格式
<!-- app.component.html --> ... <div> <label>Email</label> <input type="email" name="email" [ngModel]="user.email" required pattern="^[a-zA-Z0–9_.+-]+@[a-zA-Z0–9-]+.[a-zA-Z0–9-.]+$" #email="ngModel" > <small [hidden]="email.valid || (email.pristine && !f.submitted)"> Email is required and format should be <i>john@doe.com</i>. </small> </div> ...
我們把 email 設置為必填,然后使用內建的模板驗證器,通過正則表達式來檢查 email 的值:^[a-zA-Z0–9_.+-]+@[a-zA-Z0–9-]+.[a-zA-Z0–9-.]+$.
密碼和確認密碼
需求:
<!-- app.component.html --> ... <div> <label>Password</label> <input type="password" name="password" [ngModel]="user.password" required #password="ngModel"> <small [hidden]="password.valid || (password.pristine && !f.submitted)"> Password is required </small> </div> <div> <label>Retype password</label> <input type="password" name="confirmPassword" [ngModel]="user.confirmPassword" required validateEqual="password" #confirmPassword="ngModel"> <small [hidden]="confirmPassword.valid || (confirmPassword.pristine && !f.submitted)"> Password mismatch </small> </div> ...
validateEqual 是我們自定義的驗證器。它會將當前輸入的值與輸入的密碼值進行對比驗證。
# 自定義確認密碼驗證器
我們將制定一個 validate equal 指令。
// equal-validator.directive.ts import { Directive, forwardRef, Attribute } from '@angular/core'; import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; @Directive({ selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]', providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true } ] }) export class EqualValidator implements Validator { constructor( @Attribute('validateEqual') public validateEqual: string) {} validate(c: AbstractControl): { [key: string]: any } { // self value (e.g. retype password) let v = c.value; // control value (e.g. password) let e = c.root.get(this.validateEqual); // value not equal if (e && v !== e.value) return { validateEqual: false } return null; } }
代碼很長,讓我們把它拆開一部分一部分地看。
申明指令
// equal-validator.directive.ts @Directive({ selector: '[validateEqual][formControlName],[validateEqual] [formControl],[validateEqual][ngModel]', providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true } ] })
首先,我們使用 @Directive 注解定義指令。然后我們指定 selector。selector 是必須的。我們會擴展內建驗證器集合 NG_VALIDATORS 來將我們的等值驗證器用于 providers.
// equal-validator.directive.ts export class EqualValidator implements Validator { constructor( @Attribute('validateEqual') public validateEqual: string) {} validate(c: AbstractControl): { [key: string]: any } {} }
我們的指令類必須實現 Validator 接口。Validator 接口需要 avalidate 函數。在構建函數中,我們通過 @Attribute('validateEqual') 注解注入屬性值,并將其賦值給 validateEqual 變量。在我們的示例中, validateEqual 的值是 "password" 。
實現驗證
// equal-validator.directive.ts validate(c: AbstractControl): { [key: string]: any } { // 自己的值 (如 retype password) let v = c.value; // 控件的值 (如 password) let e = c.root.get(this.validateEqual); // 值不等旱 if (e && v !== e.value) return { validateEqual: false } return null; }
首先我們從輸入控件讀入值,賦給 v。然后我們在表單中找到 password 控件的值賦值給 e。之后檢查值是否相等,如果不等就返回錯。
# 在應用模塊中導入自定義驗證器
要使用自定義驗證器,需要先將其導入到應用程序模塊中。
// app.module.ts ... import { EqualValidator } from './equal-validator.directive'; // 導入驗證器 import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [ AppComponent, EqualValidator ], // 導入到應用模塊 bootstrap: [ AppComponent ], }) ...
好了!假如你在 password 字段中輸入 "123",在 retype password 字段中輸入"xyz",就會顯示一個密碼不匹配的錯誤。
# 看起來挺好,但是……
現在一切都挺好,直到你 在 retype passowrd 中輸入文本之后 又修改了 password 字段的值。
比如,你在 password 字段中輸入 "123",在 retype password 字段中也輸入 "123", 然后將 password 字段的值改為 "1234" 。驗證仍然通過。 為什么?
因為我們只把等值驗證器應用到 retype password 字段。只有當 retype password 的值發生變化時才會觸發驗證。
解決辦法
有幾種方法可以解決這個問題。我們這里只討論其中一種,你自己可以去找到其它辦法。我們會再次使用 validateEqual 驗證器并 添加 一個 reverse 屬性。
<!-- app.component.html --> ... <input type="password" class="form-control" name="password" [ngModel]="user.password" required validateEqual="confirmPassword" reverse="true"> <input type="password" class="form-control" name="confirmPassword" [ngModel]="user.confirmPassword" required validateEqual="password"> ...
在我們的例子中,我們設置 password 驗證的 reverse 為 true。只要 password 與 retype password 的 值不等,我們會為確證密碼字段添加一個錯誤消息,而不是重置 password 字段。
完整的自定義驗證器代碼如下:
// equal-validator.directive.ts import { Directive, forwardRef, Attribute } from '@angular/core'; import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; @Directive({ selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]', providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true } ] }) export class EqualValidator implements Validator { constructor(@Attribute('validateEqual') public validateEqual: string, @Attribute('reverse') public reverse: string) { } private get isReverse() { if (!this.reverse) return false; return this.reverse === 'true' ? true: false; } validate(c: AbstractControl): { [key: string]: any } { // self value let v = c.value; // control vlaue let e = c.root.get(this.validateEqual); // value not equal if (e && v !== e.value && !this.isReverse) { return { validateEqual: false } } // value equal and reverse if (e && v === e.value && this.isReverse) { delete e.errors['validateEqual']; if (!Object.keys(e.errors).length) e.setErrors(null); } // value not equal and reverse if (e && v !== e.value && this.isReverse) { e.setErrors({ validateEqual: false }); } return null; } }
當然,還有其他方法也能解決密碼和確認密碼驗證問題。有些人建議在組( stack overflow )中添加密碼和確認密碼的機制,然后驗證它。
方法沒有絕對的好與壞,適合自己的才是最好的。
以上所述是小編給大家介紹的在 Angular2 中實現自定義校驗指令(確認密碼)的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。