【问题标题】:Angular conditional form validatorAngular 条件表单验证器
【发布时间】:2019-02-11 13:39:35
【问题描述】:

我知道网络上有很多关于同一主题的主题,但我无法找到适合我的解决方案。

我有一个用angular的formBuilder制作的表单,它是一个配置文件表单,我们可以在其中更改密码,所以我们输入了三个密码:旧密码,新密码和新密码确认。

这是表格:

this.editProfileForm = this.formBuilder.group({
  lastname: ['', Validators.required],
  firstname: ['', Validators.required],
  email: ['', [Validators.required, Validators.email]],
  phone: [this.phone.replace(/\s/g, ''), [Validators.pattern('[0-9]{10}')]],
  birthdate: ['', [Validators.required]],
  password: [''],
  new_password: [''],
  new_password_confirm: [''],
});
this.editProfileForm.setValidators([this.ageValidator, this.samePasswordValidator, this.requiredPasswordValidator]);

我尝试做的是仅在其中一个不为空时才设置密码字段。如果用户开始输入其中一个密码字段,那么这三个字段都是必需的。

这是我的尝试:

public requiredPasswordValidator(form: FormGroup): any {
  if (form.controls.password.value || form.controls.new_password.value || form.controls.new_password_confirm.value) {

    form.controls.password.setValidators([Validators.required]);
    form.controls.new_password.setValidators([Validators.required, Validators.minLength(6)]);
    form.controls.new_password_confirm.setValidators([Validators.required, Validators.minLength(6)]);
  }
}

这似乎有效,但并不完美,只有当我开始输入并擦除这些字段时才需要这些字段,并且每个字段都是如此。例如,如果我输入密码字段,则不需要 new 和 new_confirm,但如果我在新的 pw 输入中输入一个随机字母并将其删除,则该字段是必需的。

我不知道我的解释是否真的很清楚,如果您需要更多信息,请咨询我。

谢谢。

编辑

我尝试了 Ankur Jain 解决方案,但仍然遇到同样的问题:

这里是函数:

public formControlValueChanged(): void {
    this.editProfileForm.get('password').valueChanges.subscribe(
      (mode: string) => {
        if (mode) {
          this.f.new_password.setValidators([Validators.required]);
          this.f.new_password_confirm.setValidators([Validators.required]);
        }
      });
  }

(我使用 this.f 是因为使用 juste new_password 和 new_password 确认它会引发错误,this.f 是一个返回 editProfileForm.controls 的函数)

我在 ngOninit 中调用它:

  this.formControlValueChanged();

我也尝试将this.editProfileForm.updateValueAndValidity(); 添加到函数中,但这没有任何改变。

【问题讨论】:

  • 为什么不尝试在所有可以返回三个对象数组的 formGroup 上创建一个自定义验证器(其中一些可以为空)?

标签: angular forms validation


【解决方案1】:

据我了解,如果其中一个字段中有某些值,则您希望为所有人设置必需的值,否则,它们不是必需的。因此,让我们检查一下,如果其中一个字段有值,请在表单上设置错误...例如{ allRequired: true }。如果所有控件都有值,则返回null

passwordsValidator(form: FormGroup): any {
  const ctrls = form.controls;
  if (ctrls.password.value && ctrls.new_password.value && ctrls.new_password_confirm.value) {
    return null;
  } else if (ctrls.password.value || ctrls.new_password.value || ctrls.new_password_confirm.value) {
    return { allRequired: true}
  }
  return null;
}

然后我们可以使用hasError在模板中显示错误:

<p *ngIf="editProfileForm.hasError('allRequired')">Password fields are required!</p>

这是一个StackBlitz

【讨论】:

  • 我试过这样的解决方案,问题是当三个输入有一个值时,错误仍然在表单上,​​所以他无效
  • @Jess 哦,对不起,我昨天一定很累 :D 现在已经修好了,应该可以按你的意愿工作了 :)
  • 我认为我有问题,因为当我开始在字段上输入时,我的错误消息没有直接显示,但您的解决方案似乎不错
  • 您能否在我制作的 StackBlitz 中分叉并尝试复制您的问题,我很乐意看看 :)
  • 它可以工作(我只是忘记了我的 html 的条件),谢谢
【解决方案2】:

您可以订阅表单的值更改事件。

formControlValueChanged() {
    this.editProfileForm.get('password').valueChanges.subscribe(
       (mode: string) => {
           if(mode){ 
               new_password.setValidators([Validators.required]);
               new_password_confirm.setValidators([Validators.required]);
            }
        });
}

在 ngOnInit 中:

ngOnInit() {
    this.formControlValueChanged();
}

【讨论】:

  • 我正在尝试使用您的解决方案,但我遇到了同样的问题,只有当我在字段中输入内容并将其删除时,验证器才会“激活”。
【解决方案3】:

调用setValidators()后尝试这样做:

form.controls.password.updateValueAndValidity();
form.controls.new_password.updateValueAndValidity();
form.controls.new_password_confirm.updateValueAndValidity();

根据文档,updateValueAndValidity

重新计算控件的值和验证状态。

【讨论】:

  • 我试图做form.updateValueAndValidity(); 并且通过这个或你的回答我得到一个错误“超出最大调用堆栈大小”,我认为是因为表单已更新,因此再次调用验证器,并且表格再次更新,等等...
  • @Jess 这个解决方案不适合你吗? -> stackoverflow.com/questions/51605737/…
  • 如果密码输入被触摸,这个解决方案似乎只是显示一条错误消息,如果一个不为空,我想将所需的验证器添加到我的字段中,如果它们为空则删除验证器跨度>
猜你喜欢
  • 2016-10-26
  • 1970-01-01
  • 2022-12-22
  • 2015-11-30
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-13
  • 2019-07-31
相关资源
最近更新 更多