溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在 Angular2 中實現(xiàn)自定義校驗指令(確認密碼)的方法

發(fā)布時間:2020-09-03 12:29:56 來源:腳本之家 閱讀:234 作者:mrr 欄目:web開發(fā)

我們會在本文中探索 Angular 2 內建的自定義驗證。

# 介紹

Angular 2 原生就支持一些有用的驗證器:

  1. required: 驗證字段必須存在
  2. minlength: 驗證字段值的最小長度有效
  3. maxlength: 驗證字段值的最大長度有效
  4. pattern: 驗證輸入的值是否匹配給定的模板,比如 email

我們會基于下面的接口創(chuàng)建一個表單來獲取用戶信息。

// 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.
}

需求

僅在字段數(shù)據(jù)不正確或提交表單的時候,為每個字段 顯示錯誤消息 。

UI 展示:

在 Angular2 中實現(xiàn)自定義校驗指令(確認密碼)的方法 

# 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 組件

讓我們繼續(xù)創(chuàng)建 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>

現(xiàn)在來一個個添加控件。

用戶名

需求: 必填,長度在 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 標簽在開發(fā)過程中對調試很有用。它會顯示字段的所有驗證錯誤。

電子郵件地址

需求: 必填,必須是有效的電子郵件地址格式

<!-- 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-.]+$.

密碼和確認密碼

需求:

  1. 密碼: 必填,值必須與確認密碼的值相同。
  2. 確認密碼: 必填,值必須與密碼的值相同。
<!-- 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 } {}
}

我們的指令類必須實現(xiàn) Validator 接口。Validator 接口需要 avalidate 函數(shù)。在構建函數(shù)中,我們通過 @Attribute('validateEqual') 注解注入屬性值,并將其賦值給 validateEqual 變量。在我們的示例中, validateEqual 的值是 "password" 。

實現(xiàn)驗證

// 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",就會顯示一個密碼不匹配的錯誤。

# 看起來挺好,但是……

現(xiàn)在一切都挺好,直到你 在 retype passowrd 中輸入文本之后 又修改了 password 字段的值。

比如,你在 password 字段中輸入 "123",在 retype password 字段中也輸入 "123", 然后將 password 字段的值改為 "1234" 。驗證仍然通過。 為什么?

因為我們只把等值驗證器應用到 retype password 字段。只有當 retype password 的值發(fā)生變化時才會觸發(fā)驗證。

解決辦法

有幾種方法可以解決這個問題。我們這里只討論其中一種,你自己可以去找到其它辦法。我們會再次使用 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">
...
  • reverse 是 false 或者沒有設置的情況下,我們會像前一節(jié)提到的那樣執(zhí)行等值驗證器。
  • reverse 是 true 的時候,我們仍然會執(zhí)行等值驗證器,但它不會為當前控件添加錯誤消息,而是 為指定 會把的目標控件添加錯誤消息 。

在我們的例子中,我們設置 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 中實現(xiàn)自定義校驗指令(確認密碼)的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網(wǎng)站的支持!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI