This article DEMO address: source code or final effect

In the Angular, a new way of thinking about dynamic form validation , we gave three methods for field validation in Angular projects. In this article, we will focus on the first method to discuss.

Suppose you have the following application:
image.png

The function of this application is to judge the parity of the input value. If the condition is met, the Submit button will be enabled, otherwise it will not be enabled.

Cross field validation

Since the validation of input values is differentiated according to the input type, here we need a validator that spans input types and input values:

  ngOnInit(): void {
    this.formGroup.setValidators((formGroup) => {
      formGroup = formGroup as FormGroup;
      const type = formGroup.get('type').value as number;
      if (type === 0) {
        // 验证是否是偶数 1️⃣
      } else {
        // 验证是否为奇数 1️⃣
      }
    });
  }

Although we can directly write the logic of the validator at 1️⃣, from the perspective of division of labor, this is often the worst solution.
For this, we also prepare the validator:


/**
 * 数字校验器
 */
export class NumberValidator {
  /**
   * 偶数校验器
   */
  static isEven(control: AbstractControl): ValidationErrors | null {
    const value = +control.value as number;
    if (Number.isInteger(value) && value % 2 === 0) {
      return null;
    } else {
      return { isEven: '输入的数字不是偶数' };
    }
  }

  /**
   * 奇数校验器
   */
  static isOdd(control: AbstractControl): ValidationErrors | null {
    const value = +control.value as number;
    if (Number.isInteger(value) && value % 2 === 1) {
      return null;
    } else {
      return { isOdd: '输入的数字不是奇数' };
    }
  }
}

Use a standalone validator

With a stand-alone validator, we can use code like the following to call directly in the cross-field validator:

  ngOnInit(): void {
    this.formGroup.setValidators((formGroup) => {
      formGroup = formGroup as FormGroup;
      const type = formGroup.get('type').value as number;
      if (type === 0) {
        return NumberValidator.isEven(formGroup.get('value')); 🟢
      } else {
        return NumberValidator.isOdd(formGroup.get('value')); 🟢
      }
    });
  }

Yes, you can pass in the FormControl that needs to be verified when calling.

If our cross-field validator needs to verify multiple fields at the same time, we can also do this:

        const result = {
          ...Validators.required(formGroup.get(this.formKeys.image)),
          ...Validators.required(formGroup.get(this.formKeys.imageLeftTopPoint)),
          ...Validators.required(formGroup.get(this.formKeys.imageRightBottomPoint)),
          ...MapPointValidator.isPoint(formGroup.get(this.formKeys.imageLeftTopPoint)),
          ...MapPointValidator.isPoint(formGroup.get(this.formKeys.imageRightBottomPoint))
        }

        return Object.keys(result).length === 0 ? null : result; 🟩

🟩 The returned error message is judged. If the length is 0, it means that {} null returned directly. Otherwise, the error message after splicing multiple validators is returned.

If you want to see the specific code and effect, please click: sample code or final effect


潘杰
3.1k 声望239 粉丝