Angular 如果另一个属性设置为false,则忽略FormBuilder属性验证程序规则

Angular 如果另一个属性设置为false,则忽略FormBuilder属性验证程序规则,angular,Angular,在Angular 2-5中使用FormBuilder时,如果FormBuilder组中的另一个属性设置为true/false,是否可以忽略验证程序规则 以下面的代码示例为例: this._fb.group({ "stake": [data.stake, Validators.compose([Validators.min(1), Validators.required])], "isSelected": data.isSelected }); 如果在表单中将isSelect

在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随附的
设置验证程序
清除验证程序
更新值和有效性
功能的组合

以下是一个例子:

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()
,以强制执行验证周期

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

监视选中的
表单控件值中的更改的一种方法是订阅该控件可观察到的
值更改
,并根据订阅中返回的值运行对
stack
控件的验证程序更改

见下文:

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();
    });

我认为最好的解决方案是将验证登录移动到
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 });
  }

}
从'@angular/core'导入{Component};
从'@angular/forms'导入{Validators,ValidatorFn,FormGroup,FormControl,FormBuilder};
常量myValidator:ValidatorFn=(fg:FormGroup)=>{
const stack=fg.get('stack');
const isSelected=fg.get('isSelected');
如果(isSelected.value){
返回null;
}
const result=Validators.compose([Validators.required,Validators.min(5)])(stake);
return!result | |(!result.min&&!result.required)?null:{myError:true};
}
@组成部分({
选择器:“我的应用程序”,
模板:`
被选中
{{form.valid}
`,
样式URL:['./app.component.css']
})
导出类AppComponent{
表格:表格组;
构造函数(私有fb:FormBuilder){
this.form=this.fb.group({
桩号:[null],
isSelected:[null]
},{validator:myValidator});
}
}

非常感谢您的回答。如何将SetTakeValidators()设置为表单组中的isSelected?到目前为止,我还没有这样做,但它抛出了一个错误(script.js),我文章的最后一部分是观察
isSelected
字段中的更改的最好方法。它订阅该控件可观察到的
值更改。也许,在return语句之前将其添加到
buildArray
。然后你可以一起去掉
SetTakeValidators
函数。再次感谢你-我再次添加了它,但这里还有一个错误,我也应该提到,在动态添加组时,表单中可能会有几个“isSelected”,有点像购物车项目。如果有多个isSelected,订阅仍然有效吗?如果您将所有代码都包含在plunk中,会更容易帮助您。好的,很好。尝试将整个订阅代码块移动到此行下:
this.betsForm=this.createFormGroup(this.betSlipItems)。我也在答案中加入了这一点。您只需等待
this.betsForm
启动,然后再尝试订阅其中的内容。