Angular Form Validation - 表单验证

·  阅读 1363

Angular中,form表单的验证功能是非常重要且实用的,下面来具体看一下如何正确的使用Angular表单验证:

  1. angular 内置验证器

    首先,Angular中提供了一系列的内置验证器,如required,min,minLength等。

    下面构建一个简单的表单与loginForm绑定,其中包含两个input,分别为name和password:

    <form [formGroup]='loginForm'>
      <div>
        name: <input type="text" formControlName='name' forbiddenName='any'>
        <span *ngIf='name.invalid && (name.dirty || name.touched)'>
          <span *ngIf='name.errors.required'>name不能为空</span>
          <span *ngIf='name.errors.minlength'>name不能少于两个字符</span>
        </span>
      </div>
      <div>
        password: <input type="password" formControlName='password'>
        <span *ngIf='password.invalid && (password.dirty || password.touched)'>
          <span *ngIf='password.errors.required'>password不能为空</span>
        </span>
      </div>
      <button type="submit">Submit</button>
    </form>
    
    复制代码

    在组件初始化时,对loginForm进行实例化,并且为name和password都绑定了表单控件FormControl;在FormControl实例化过程中,传入了两个参数,第一个参数为控件的初始化值;第二个参数则是应用到控件上的同步验证器数组;FormControl可以接受第三个参数进行异步验证,此时暂且忽略。

    ​ 为name控件设置了两个验证器:Validators.required和Validators.minLength(2),分别验证name字段必填项且长度不小于2;password控件也为必填项。

    ​ 同时,为name和password属性添加了getter方法,这样能够简化在html模板中的代码,可以直接使用name.errors.required或取错误信息,相当于使用loginForm.get('name').errors.required

    ​ 另外,还添加了name.invalid && (name.dirty || name.touched)的验证,以在保证用户未输入前不显示错误信息。

    export class FormDemoComponent implements OnInit {
    
      loginForm: FormGroup;
      constructor() { }
    
      ngOnInit(): void {
        this.loginForm = new FormGroup({
          name: new FormControl('default name', [
            Validators.required,
            Validators.minLength(2)
          ]),
          password: new FormControl('', [
            Validators.required
          ])
        });
      }
    
      get name() {
        return this.loginForm.get('name');
      }
      get password() {
        return this.loginForm.get('password');
      }
    }
    复制代码
  2. 自定义验证器

    除了Angular提供的内置验证器外,也可以给控件添加自定义的验证器,如自定义一个验证器,验证name中不能是admin。

    定义如下的验证器函数customNameValidation(),它实际返回一个配置好的验证器函数。该函数接受一个AbstractControl对象,控制器值合法时返回null,不合法则返回验证错误的对象,invalidName作为其中的属性名。

    customNameValidation(): ValidatorFn {
        return (control: AbstractControl): { [key: string]: any } | null => {
          if (control.value === 'admin') {
            return { 'invalidName': { value: control.value } };
          } else {
            return null;
          }
        };
      }
    复制代码

    将上述自定义的验证器,传入name控件的同步验证器数组中:

    this.loginForm = new FormGroup({
      name: new FormControl('default name', [
        Validators.required,
        Validators.minLength(2),
        this.customNameValidation() // 自定义验证器
      ]),
      password: new FormControl('', [
        Validators.required
      ])
    });
    复制代码

    与内置验证器一致,在对应的HTML模板中,可以通过name.errors.invalidName获取错误,如下显示错误信息:

     <span *ngIf='name.errors.invalidName'>name不能为admin</span>
    复制代码
  3. 自定义验证器指令

    除了在FormControl中添加自定义验证器之外,也可以通过指令(directive)的形式,通过html模板添加验证器。

    新建一个ForbiddenNameDirective,使它符合Angular form模块中提供的Validator接口,注意要将此指令注册到NG_VALIDATORS提供商中,且使用useExisting进行实例化;在validate方法中,调用自定义的验证器函数forbiddenNameValidation(),该方法接受一个string类型的参数,作为name字段不可用的特殊字符串。

    import { Directive, Input } from '@angular/core';
    import { ValidatorFn, AbstractControl, Validator, NG_VALIDATORS } from '@angular/forms';
    
    export function forbiddenNameValidation(regName: string): ValidatorFn {
      return (control: AbstractControl): { [key: string]: any } => {
        if (control.value === RegName) {
          return { 'forbiddenName': { value: control.value } };
        }
      };
    }
    
    @Directive({
      selector: '[forbiddenName]',
      providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenNameDirective, multi: true}]
    })
    export class ForbiddenNameDirective implements Validator {
    
      @Input() forbiddenName: string;
    
      constructor() { }
    
      validate(control: AbstractControl): { [key: string]: any } | null {
        return this.forbiddenName ? forbiddenNameValidation(this.forbiddenName)(control) : null;
      }
    }
    复制代码

    与前一个例子稍有不同,因为并没有将不合法的name设为固定值,在模板中使用该指令可以传入该值,此处以‘any’为例forbiddenName='any'

     name: <input type="text" formControlName='name' forbiddenName='any'>
        <span *ngIf='name.invalid && (name.dirty || name.touched)'>
          <span *ngIf='name.errors.forbiddenName'>name不能为any</span>
        </span>
    复制代码
  4. 跨字段交叉验证

    除了对单个控件进行验证外,angular也支持跨字段进行交叉验证,可以在FormGroup进行自定义验证;如验证name和password值不能相同。

    首先,自定义一个验证器,返回一个配置好的验证器函数;在实例化FormGroup,把新建的验证器传给第二个参数:

    customNameValidation(): ValidatorFn {
      return (control: AbstractControl): { [key: string]: any } | null => {
        if (control.value === 'admin') {
          return { 'invalidName': { value: control.value } };
        } else {
          return null;
        }
      };
    }
    
    buildFormGroup() {
      this.loginForm = new FormGroup({
        name: new FormControl(),
        password: new FormControl()
      }, {validators: this.customGroupValidator});
    }
    复制代码

    在html模板中,使用loginForm.errors?.namePasswordSame获取错误信息:

    <span *ngIf='loginForm.errors?.namePasswordSame'> name and password can not be same!</span>
    复制代码
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改