Angular 2 反应式表单自定义验证器仅在表单控件有效时应用



如何实现仅在表单控件有效时才应用的自定义验证器?

像这样的东西将是理想的:

static isValid(control: FormControl) {
    if (control.valid) {
        // custom validation checks here
        return {isNotValid: true};
    }
    return null;
}

但这里的control.valid总是正确的,所以即使其他人会使该字段无效,它也将被应用。

有没有办法实现这一目标?

详细示例

源代码在这里: https://stackblitz.com/edit/angular-conditional-validator

app.component.ts

import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { MyValidator } from './validators.service';
@Component({
  selector: 'my-app',
  template: `
    <form>
      <label>Name:</label>
      <input [formControl]="form.get('name')">
    </form>
  `
})
export class AppComponent  {
  form = new FormGroup ({
    name: new FormControl('', [
      MyValidator.isValidString,
      MyValidator.isValidName,
    ])
  });
}

validators.service.ts

import { FormControl } from '@angular/forms';
export class MyValidator {
  static isValidString(control: FormControl) {
    if (!control.value || typeof control.value !== 'string') {
      return {isNotValidString: true};
    }
    return null;
  }
  static isValidName(control: FormControl) {
    if (control.valid && control.value !== 'John Doe') {
      return {isNotValidName: true};
    }
    return null;
  }
}

如何使验证器仅在控制有效时才应用/执行isValidName,即先前的验证器返回null?因为现在,我相信angular将首先运行所有同步验证器,然后运行所有异步验证器,然后才设置控制状态,我认为这是正确的方法。

注意
此示例仅用于演示,它没有真正的实时应用程序。

实现此目的的最简单方法是创建一个辅助函数:
validators.service.ts

import { AbstractControl, FormControl, ValidationErrors, ValidatorFn } from "@angular/forms";
export function runInOrder(validators: ValidatorFn[]): ValidatorFn {
  return (c: AbstractControl): ValidationErrors | null => {
    for (const validator of validators) {
      const resp = validator(c);
      if (resp != null) {
        return resp;
      }
    }
    return null;
  };
}
export class MyValidator {
  // ...
}

并将其用作自定义验证器:
app.component.ts

import { MyValidator, runInOrder } from "./validators.service";
// ...
export class AppComponent {
  form: FormGroup = new FormGroup({
    name: new FormControl("", runInOrder([
      MyValidator.isValidString,
      MyValidator.isValidName
    ]))
  });
}

完整示例:
https://stackblitz.com/edit/angular-conditional-validator-solution

尝试访问父属性,假设 isValid 验证器适用于表单控件的第一级子控件,或者递归地找到顶部的父级

static isValid(control: FormControl) {
    if(control.parent) {
       if(control.parent.valid) {
       //custom validation
       }
    }
 return null;
}

最新更新