【问题标题】:Ignore FormBuilder property validator rule if another property is set to false如果另一个属性设置为 false,则忽略 FormBuilder 属性验证器规则
【发布时间】:2018-04-13 20:52:05
【问题描述】:

在 Angular 2-5 中使用 FormBuilder 时,如果 FormBuilder 组中的另一个属性设置为 true/false,是否可以忽略验证器规则?

以如下代码为例:

this._fb.group({
    "stake": [data.stake, Validators.compose([Validators.min(1), Validators.required])],
    "isSelected": data.isSelected
  });

如果在表单中将 isSelected 设置为 true,有没有办法忽略 stake 中的验证器?

谢谢

【问题讨论】:

    标签: angular


    【解决方案1】:

    为了做到这一点,您必须使用 Angular AbstractControl 附带的 setValidatorsclearValidatorsupdateValueAndValidity 函数的组合。

    这是一个例子:

    isSelected: boolean;
    form: FormGroup;
    setStakeValidators(): void {
        const stakeControl = this.form.get('stake');
        if (this.isSelected === false) {
            stakeControl.setValidators([Validators.min(1), Validators.required]);
        } else {
            stakeControl.clearValidators();
        }
        stakeControl.updateValueAndValidity();
    }
    

    在这个示例函数中,您首先从您正在使用的FormGroup 获得stake 控件。然后,根据isSelected 的值,您可以将验证器设置为您需要的验证器,或者清除它们以便不会进行验证。之后,由于表单不会自动重新验证,因此您在控件上运行 updateValueAndValidity() 以强制进行验证循环。

    您会在我上面包含的文档链接中注意到,如果您使用异步验证器,这些函数有异步版本可用。

    观察isSelected 表单控件值变化的一种方法是订阅该控件的valueChanges observable,并根据订阅中返回的值运行验证器对stake 控件的更改。

    见下文:

    this.form.get('isSelected').valueChanges.subscribe(value => {
        const stakeControl = this.form.get('stake');
        if (value === false) {
            stakeControl.setValidators([Validators.min(1), Validators.required]);
        } else {
            stakeControl.clearValidators();
        }
        stakeControl.updateValueAndValidity();
    })
    

    更新:

      this.betsForm = this.createFormGroup(this.betSlipItems);
      this.betsForm.get('isSelected').valueChanges.subscribe(value => { // console error here: TypeError: Cannot read property 'valueChanges' of null
          const stakeControl = this.betsForm.get('stake');
          if (value === false) {
            stakeControl.setValidators([Validators.min(1), Validators.required]);
          } else {
            stakeControl.clearValidators();
          }
          stakeControl.updateValueAndValidity();
        });
    

    【讨论】:

    • 非常感谢您的回答。我应该如何在表单组中将 setStakeValidators() 设置为 isSelected?我到目前为止,但它抛出一个错误(script.js)plnkr.co/edit/yoWX0gbBQ4i3tMdn0spV?p=info
    • 我帖子的最后一部分是观察isSelected 字段变化的最佳方式。它订阅了该控件的valueChanges observable。也许,在 return 语句之前将其添加到您的 buildArray 中。然后你可以一起摆脱setStakeValidators函数。
    • 再次感谢您-我再次添加了它,但这里仍然出现另一个错误plnkr.co/edit/yoWX0gbBQ4i3tMdn0spV?p=info 我还应该提到,随着组是动态添加的,表单中可能有多个“isSelected”-有点像购物车物品。如果有多个 isSelected,该订阅是否仍然有效?
    • 如果您在 plunk 中包含 所有 代码,对您的帮助会更容易一些。
    • 好的,很好。尝试在这一行下移动整个订阅代码块:this.betsForm = this.createFormGroup(this.betSlipItems);。我也将其添加到答案中。您只需等待this.betsForm 启动,然后再尝试订阅其中的内容。
    【解决方案2】:

    我认为最好的解决方案是将验证登录移动到FormGroup 本身。毕竟这是一个交叉验证的例子,其中部分验证逻辑依赖于多个表单元素。

    import { Component } from '@angular/core';
    import { Validators, ValidatorFn, FormGroup, FormControl, FormBuilder } from '@angular/forms';
    
    const myValidator: ValidatorFn = (fg: FormGroup) => {
      const stake = fg.get('stake');
      const isSelected = fg.get('isSelected');
    
      if (isSelected.value) {
        return null;
      }
    
      const result = Validators.compose([Validators.required, Validators.min(5)])(stake);
    
      return !result || (!result.min && !result.required) ? null : { myError: true };
    }
    
    @Component({
      selector: 'my-app',
      template: `
       <form [formGroup]="form">
        <input type="checkbox" formControlName="isSelected" >Is Selected
        <input type="number" formControlName="stake" />
       </form>
    
       {{ form.valid }} 
    
      `,
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
    
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
          stake: [null],
          isSelected: [null]
        }, { validator: myValidator });
      }
    
    }
    

    Live demo

    【讨论】:

      猜你喜欢
      • 2022-01-04
      • 2020-03-05
      • 1970-01-01
      • 2011-07-19
      • 2014-10-18
      • 2018-05-15
      • 1970-01-01
      • 2015-04-01
      • 1970-01-01
      相关资源
      最近更新 更多