【问题标题】:Angular 2 reactive forms custom validator apply only when form control is validAngular 2 反应式表单自定义验证器仅在表单控件有效时适用
【发布时间】:2018-06-16 03:58:02
【问题描述】:

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

这样的东西是理想的:

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

注意
此示例仅用于演示,没有实际应用。

【问题讨论】:

  • 为什么control.valid 总是有效的?编辑您的问题以添加一个最低限度的可验证示例。
  • @HDJEMAI 我已更新问题并添加了指向实时示例的链接。希望这能澄清我的困境。
  • 你能解释一下这里的用例吗,为什么你只需要在控制有效时才应用它?为什么现在这样的代码就不行了?
  • 首先,对于错误,我只想显示相关的错误消息。其次,为了减少无用的计算,这段代码只是一个模拟,在实际应用中验证器显然更复杂,可能会对性能产生一些影响。

标签: angular validation angular-reactive-forms


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    尝试访问 parent 属性,假设 isValid 验证器用于表单控件的第一级子控件,否则递归查找顶部的父控件

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

    【讨论】:

      猜你喜欢
      • 2019-03-08
      • 2020-04-06
      • 2020-01-13
      • 1970-01-01
      • 2019-02-21
      • 2017-08-28
      • 2019-05-20
      • 2021-11-01
      • 1970-01-01
      相关资源
      最近更新 更多