Angular 角度条件形式验证器

Angular 角度条件形式验证器,angular,forms,validation,Angular,Forms,Validation,我知道网络上有很多关于同一主题的话题,但我无法找到适合我的解决方案 我用angular的formBuilder制作了一个表单,这是一个配置文件表单,我们可以在其中更改密码,因此我们有三个密码输入:旧密码、新密码和新密码确认 表格如下: this.editProfileForm = this.formBuilder.group({ lastname: ['', Validators.required], firstname: ['', Validators.required], ema

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

我用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
是因为使用just new\u password和new\u password confirm会抛出错误,
this.f
是一个返回
editProfileForm.controls
的函数)

我称之为恩戈尼特:

  this.formControlValueChanged();

我还尝试添加
this.editProfileForm.updateValueAndValidity()操作,但这不会改变任何内容。

在调用
setValidators()后尝试执行此操作。

根据文档,
updateValue和validity

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


调用
setValidators()
后尝试执行此操作:

根据文档,
updateValue和validity

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


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

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

ngOnInit() {
    this.formControlValueChanged();
}

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

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

ngOnInit() {
    this.formControlValueChanged();
}

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

passwordsValidator(形式:FormGroup):任意{
const ctrls=form.controls;
if(ctrls.password.value&&ctrls.new\u password.value&&ctrls.new\u password\u confirm.value){
返回null;
}else if(ctrls.password.value | ctrls.new|u password.value | ctrls.new|u password_confirm.value){
返回{allRequired:true}
}
返回null;
}
然后我们可以使用
hasError
在模板中显示错误:

密码字段是必需的


根据我的理解,这里有一个

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

passwordsValidator(形式:FormGroup):任意{
const ctrls=form.controls;
if(ctrls.password.value&&ctrls.new\u password.value&&ctrls.new\u password\u confirm.value){
返回null;
}else if(ctrls.password.value | ctrls.new|u password.value | ctrls.new|u password_confirm.value){
返回{allRequired:true}
}
返回null;
}
然后我们可以使用
hasError
在模板中显示错误:

密码字段是必需的



这里有一个

我正试图执行
表单.updateValueAndValidity()根据这个或您的回答,我得到了一个错误“超过了最大调用堆栈大小”,我想这是因为表单已更新,因此再次调用验证程序,并再次更新表单,等等…@Jess此解决方案不适合您吗?->这个解决方案似乎只是在触摸密码输入时显示一条错误消息,如果其中一个字段不为空,我想将所需的验证器添加到我的字段中,如果为空,则删除验证器。我正在尝试执行
form.updateValueAndValidity()根据这个或您的回答,我得到了一个错误“超过了最大调用堆栈大小”,我想这是因为表单已更新,因此再次调用验证程序,并再次更新表单,等等…@Jess此解决方案不适合您吗?->此解决方案似乎只是显示一条错误消息,如果密码输入被触动,我想在我的字段中添加所需的验证器(如果其中一个字段不为空),并在字段为空时删除验证器。我正在尝试使用您的解决方案,但我遇到了相同的问题,只有当我在字段中输入某个内容并将其删除时,验证程序才会被“激活”。我正在尝试使用您的解决方案,但我遇到了相同的问题,只有当我在字段中输入某个内容并将其删除时,验证程序才会被“激活”。为什么不尝试在所有可以返回三个对象数组的formGroup上创建一个自定义验证程序(其中一些可以为空)?为什么不尝试在所有formGroup上创建一个自定义验证器,该验证器可以返回三个对象的数组(其中一些可以为空)?我尝试过这样的解决方案,问题是当三个输入有一个值时,错误仍然在表单上,所以他没有valid@Jess哦,对不起,我昨天一定很累了:D现在修好了,应该可以按你的意愿工作了:)我想我有一个问题,因为当我开始在一个字段上输入时,我的错误消息没有直接显示出来,但是你的解决方案似乎很好。你能在我做的StackBlitz中尝试复制你的问题吗?我很乐意看一看:)它有效(我只是忘记了一个条件o