Angular Reactive 形式:指定何时验证

问题描述 投票:0回答:2

条件验证器可能被问了很多次。但我永远找不到这个验证器何时被调用。

假设我有一个只有两个字段的表单

this.form = formBuilder.group({
  emailRequired: [false],
  emailRecipients: ['']
});

我现在希望仅当

emailRecipients
字段设置为
emailRequired
时,字段
true
才有必需的验证器。我想出了这个

const emailRecipientsControl = fb.control('', {
    validators: [
        (x) =>
        {
            // When emailRequired is set to true, the email control is required.
            if (x.parent?.get('emailRequired').value)
            {
                return { required: true }
            };
            return null;
        }
    ]
});
this.form = this.fb.group({
    emailRequired: [false],
    emailRecipients: emailRecipientsControl
});

这实际上有点工作,但问题是我的自定义验证器仅在

emailRecipients
值更改时才被调用,而我需要在
emailRecipients
emailRequired
都更改时调用它。

总结一下:如何定义何时调用(自定义)控件验证?

注意:我的真实表单比这个示例大得多,我不想订阅整个表单。

angular validation angular-reactive-forms
2个回答
2
投票

您需要订阅 valuechanges 并添加/删除验证器。

this.form = formBuilder.group({
  emailRequired: [false],
  emailRecipients: ['']
});

this.form.controls.emailRequired.valueChanges.pipe(
  /*unsubscription*/,
).subscribe(isRequired => {
  if (isRequired) {
    this.form.controls.emailRecipients.addValidators(Validators.required);
  } else {
    this.form.controls.emailRecipients.removeValidators(Validators.required);
  }
  this.form.controls.emailRecipients.updateValueAndValidity();
});

0
投票

正如你所说,如果你不使用 setValue 或更改输入,Angular 不会“自动验证”输入。因此,更简单的解决方案是在更改复选框时强制进行此验证

<input type="check" formControlName="emailRequired"
       (input)="form.controls.emailRecipients.updateValueAndValidity()">

更新 基于@MoxxiManagam 的推荐。如果我们可以定义我们的 formGroup 并且当我们需要订阅 valueChanges 或使用(输入)时不需要考虑会更好。

我们可以定义一个“valitador”,比如

export function checkControl(controlName:string)
{
  return (x:AbstractControl) =>
  {
    const control=x?.parent?.get(controlName);
    if (control)
      control.updateValueAndValidity()
      return null;
  }
}

这让我们可以写

  form = new FormGroup({
    emailRequired: new FormControl(false,checkControl('emailRecipients')),
    emailRecipients: new FormControl('',requireIf('emailRequired'))
  });

那么我们就简单了

<form [formGroup]="form">
    <input type="checkbox" formControlName="emailRequired">
    <input formControlName="emailRecipients">
    {{form.get('emailRecipients')?.errors|json}}
</form>

注意:验证器“requiredIf”就像

export function requireIf(controlName:string)
{
  return (x:AbstractControl) =>
  {
      if (x?.parent?.get(controlName)?.value && !x.value)
      {
          return { required: true }
      };
      return null;
  }
}

看到,当我们更改“复选框”时,formControl

form.controls.emailRecipiens
是updateAndValidity。

嗯,这个“验证器”使典型的重复密码验证器问题变得更加“稳健”。

export function equalsTo(controlName:string)
{
  return (x:AbstractControl) =>
  {
      const control=x?.parent?.get(controlName);
      if (control && control.value && control.value!=x.value)
      {
          return { notMatch: true }
      };
      return null;
  }
}

表格

  form2=new FormGroup({
    password:new FormControl('',checkControl('repeatPassword')),
    repeatPassword:new FormControl('',equalsTo('password'))

  })

A stackblitz

© www.soinside.com 2019 - 2024. All rights reserved.