仅当表单控件有效时,Angular 2被动表单自定义验证器才适用

时间:2018-01-06 15:30:29

标签: angular validation angular-reactive-forms

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

这样的事情是理想的:

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

但此处control.valid始终为true,因此即使其他会使该字段无效,也会应用它。

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

详细示例

此处的源代码:https://stackblitz.com/edit/angular-conditional-validator

app.component.ts

import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { MyValidator } from './my-validator';

@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,
    ])
  });
}

my-validator.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会首先运行所有同步验证器,然后运行所有异步验证器,并且只有在设置控制状态之后,这才是我认为的正确方法。

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

3 个答案:

答案 0 :(得分:0)

尝试访问控制状态,如果它有效,请执行您的逻辑

if(control.status == 'VALID') {

}

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

最简单的方法是创建一个辅助函数:
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