angular 自定義驗證器


先說"響應式表單"的用法

 

新建的文件,用來寫自定義驗證器

import { AbstractControl } from "@angular/forms";
//control是我們要驗證的表單控件, export
function beginWith(control: AbstractControl) { const result = /^13/.test(control.value); return result ? null : {'beginWith': {value: control.value}};
}

上面返回語句中的"beginWith"是我們自定義的一個錯誤類型名,如果被驗證的控件不滿足我們自定義的這個驗證規則, 控件元素的實例對象

 

在組件類文件中

//要引用自定義驗證器的文件,並且引入表單相關類
import { beginWith } from '....../上面定義驗證器函數的文件名';
import { FormGroup, FormControl, Validators } from '@angular/forms'; //Validators是ng自帶的內置驗證器類,里面有一些對html5驗證規則的封裝方法.

...

  //在constructor中定義表單控件實例,並用內置驗證器和自定義驗證器始初化
  this.heroForm = new FormGroup({     
      phone: new FormControl('蝙蝠俠', [Validators.required, Validators.minLength(4),beginWith ])
  });
 
  //一定要加上這個getter屬性,這樣在模板中才能取到name,下面模板中name.errors中的name就是通過這個getter方法取到的
  get phone() { return this.heroForm.get('name'); }

 

在模板中

<form [formGroup]="heroForm" novalidate>
    <input id="phone" name="phone" formControlName="phone" autocomplete="off">        
    <div *ngIf="phone.invalid && (phone.dirty || phone.touched)" class="alert alert-danger">
        <div *ngIf="phone.errors.required">
            必填
        </div>
        <div *ngIf="phone.errors.minlength">
            至少4個字母
        </div>
        <div *ngIf="phone.errors.beginWith">
            必須是13
        </div>
    </div>
</form>

 

上面定義的驗證器中的正則表達式是寫死了, 可以改造一下,  (這也是官方文檔的例子https://angular.cn/guide/form-validation#adding-to-reactive-forms):

export function beginWith(regExp: RegExp): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    const isMatch = regExp.test(control.value);
    return isMatch ? null : {'beginWith': {value: control.value}};
  };
}

 之前的寫法其實就是直接export(導出)一個驗證器函數(ValidatorFn),這個修改的寫法就是個工廠函數,即調用它時要傳進來一個正則表達式,它會返回一個使用這個正則表達式創建的驗證器函數(ValidatorFn),ValidatorFn是一個函數接口,參數為一個表單控件對象,返回值是一個錯誤信息對象或null(如果沒有錯誤).

 

相應的組件類中的創建表單對象的代碼也要改下:

this.heroForm = new FormGroup({
    name: new FormControl('蜘蛛俠', [Validators.required, Validators.minLength(4), beginWith(/^13/)])
});

 

 

 "響應式表單"的實現方式需要在表單組件類所在模塊( 可能是根模塊 )引入ReactiveFormsModule,

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

 

接下來看下模板驅動表單的實現方式:

用自定義指令的方式將上面寫自定義驗證器進行包裝 : 官方的原文:必須創建一個指令,它會包裝這個驗證器函數。我們使用 NG_VALIDATORS 令牌來把它作為驗證器提供出來. https://angular.cn/guide/form-validation#adding-to-reactive-forms

// 自定義驗證器
import { ValidatorFn, AbstractControl, NG_VALIDATORS, Validator } from "@angular/forms";
import { Directive, Input } from "@angular/core";

export function beginWith(nameRe: RegExp): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    const result = nameRe.test(control.value);
    return result ? null : { 'beginWith': { value: control.value } }; }; }

@Directive({
  selector: '[phone]', //在模板中的屬性指令就要寫成 phone="..."
  providers: [{
    provide: NG_VALIDATORS, //這里我還沒太搞弄,參考下官方文檔吧
    useExisting: ForbiddenValidatorDirective, //這個屬性的意思官方文檔上寫的我也沒太懂,總之呢要和下面類名一致
    multi: true //官方文檔是說要想讓一個控件同時支持多個驗證器就要寫 multi: true
  }]
})
export class ForbiddenValidatorDirective implements Validator {
  @Input('phone') regExp_str: string; //通過模板上的屬性指令取到的字符串值

  validate(control: AbstractControl): { [key: string]: any } | null {
    const regExp = new RegExp(this.regExp_str, 'i'); //創建正則表達式對象
    const validatFn = beginWith(regExp);  //直接調用上面定義的工廠函數, 它返回的是一個驗證器函數 return this.regExp_str ? validatFn(control) : null; //然后調用這個驗證器, control就是當前指令所屬的表單控件
  }
}

 

 

修改組件類的代碼:

...
export class MyApp {
  ...
  //"模板驅動式表單"的數據就直接用類屬性定義
  hero = {
    phone: '13333333333'
  };

  constructor() {
// this.heroForm = new FormGroup({
//        name: new FormControl('王寧', [Validators.required, Validators.minLength(4), beginWith(/^123/)]) // });
  }

 //get name() { return this.heroForm.get('name'); } }

 

 

然后 修改一下模板

<form>
    <input id="phone" name="phone" required minlength="11" phone="^13" [(ngModel)]="hero.phone" #phone="ngModel" autocomplete="off">

    <div *ngIf="phone.invalid && (phone.dirty || phone.touched)" >
        <div *ngIf="phone.errors.required">
            必填
        </div>
        <div *ngIf="phone.errors.minlength">
            至少11位數
        </div>
        <div *ngIf="phone.errors.beginWith">
            手機號必須是13開頭
        </div>
    </div>
</form>

 

"模板驅動式表單"中, 需要定義模板變量 #xxx="ngModel" (就是上面的#phone), 下面的錯誤提示DIV中用的phone.invalid 和 phone.dirty 等,其中的phone就是這個模板變量xxx,即指向被綁定的數據模型,這里是hero.phone

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM