JustDoItTomorrow
3/7/2018 - 1:37 PM

自定义验证器

import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } from '@angular/forms';

// forbiddenNameValidator应用在响应式表单,可以作为创建FormControl时的参数,直接传进去
// ForbiddenValidatorDirective指令可以直接写在模板上,既可以应用在响应式表单,也可以应用在模板驱动表单

// 返回配置好的验证器函数(ValidatorFn)
// 该函数接受一个Angular控制器对象,并在控制器值有效时返回null,或无效时返回验证错误对象。 
// 验证错误对象通常有一个名为验证秘钥(forbiddenName)的属性。其值为一个任意词典,我们可以用来插入错误信息({name})。
export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} => {
    const forbidden = nameRe.test(control.value);
    return forbidden ? {'forbiddenName': {value: control.value}} : null;
  };
}

@Directive({
  selector: '[appForbiddenName]',
  // 把自己注册到了NG_VALIDATORS提供商中,从而让该指令在验证的时候被调用。
  providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]
})

export class ForbiddenValidatorDirective implements Validator /*继承Validator属性*/ {
  @Input() forbiddenName: string;

  validate(control: AbstractControl): {[key: string]: any} {
    return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
                              : null;
  }
}
<!--模板驱动式的验证-->
<input id="name" name="name" class="form-control"
       required minlength="4" forbiddenName="bob"
       [(ngModel)]="hero.name" #name="ngModel" >
// 响应驱动式的验证
this.heroForm = new FormGroup({
  'name': new FormControl(this.hero.name, [
    Validators.required,
    Validators.minLength(4),
    forbiddenNameValidator(/bob/i) // <-- Here's how you pass in the custom validator.
  ]),
  'alterEgo': new FormControl(this.hero.alterEgo),
  'power': new FormControl(this.hero.power, Validators.required)
});