【问题标题】:How to dynamically add validators to the Forms in Angular 2 - 4 using FormBuilder?如何使用 FormBuilder 在 Angular 2-4 中动态添加验证器?
【发布时间】:2017-10-23 22:38:58
【问题描述】:

我正在使用 FormBuilder 构建表单:

this.myForm = this.fb.group({
  'name': new FormControl(null, Validators.min(5)),
  'description': new FormControl(null, Validators.min(60))
});

问题是我还应该验证它是否需要,我通过这样构建的地图从配置中获取它:

map = new Map<string, boolean>();
map.set('name', true);
map.set('description', false);

问题可以解决如下:

this.myForm = this.fb.group({
  'name': this.map.get('name') ? new FormControl(null, Validators.compose([Validators.required, Validators.min(5)])) : new FormControl(null, Validators.min(5)),
  'description': this.map.get('description') ? new FormControl(null, Validators.compose([Validators.required, Validators.min(60)])) : new FormControl(null, Validators.min(60))
});

这行得通,但想象一下,在具有多个字段的多个表单的大型应用程序中,这种方式真的很不舒服。理想情况下,它看起来像这样:

Object.keys(this.myForm.controls).forEach(key => {
  if (map.get(key)) {
    this.myForm.get(key).setValidators(this.myForm.get(key).getValidators().push(Validators.required))
  }
});

这种方式当然行不通。因此,如果有人已经解决了这个问题或者有一个很好的方法来做上面描述的事情,我会非常感谢你。先谢谢了!!!

更新:问题可以简化为“如何获取与 FormControl 关联的所有验证器”。我认为这个问题没有明确的解决方案 --> https://github.com/angular/angular/issues/13461

【问题讨论】:

  • 为什么这种方式行不通?
  • Angular 2-4 中不存在 .getValidators() 方法,或者至少我没有找到类似的东西。但是,如果 Angular 2 - 4 中存在 .setValidators () 方法。
  • 检查我的答案

标签: javascript angular typescript


【解决方案1】:

这是一个简单的解决方案,我在 cmets 中解释了它:

Object.keys(this.myForm.controls).forEach(key => {
        // if it needs to be required 
        if (map.get(key)) {
            // you have first to check if it already contains validator.required.
            let validators = this.myForm.controls[key].validator(this.myForm.controls[key]);
            // if it contains it -> {required: true};
            // if it doesn't contains it you can now add the required validator
            if(validators && !validators.required){
                let exisitingValidators = this.myForm.controls[key].validators;        
                this.myForm.controls[key].setValidators(Validators.compose([...existingValidators ,Validators.required]));
                // call updateValueAndValidity to apply the new validators on the control
                this.myForm.controls[key].updateValueAndValidity();                
        }
    });

希望对你有帮助:)

【讨论】:

  • 感谢您的回复。 let validators = this.myForm.controls[key].validator(''); 这会返回验证器?
  • 有什么错误吗?有效吗? @RidelHernándezInfante
  • 它不起作用,let validators = this.myForm.controls [key] .validator (''); 抛出以下错误:错误:(72, 107) TS2345: '' 类型的参数不可分配给 'AbstractControl' 类型的参数。我认为它不会返回验证器
  • 它接受AbstractControl 作为参数,我更新了答案现在试试
  • 更新您的代码后发生如下情况:let validators = this.myForm.controls [key] .validator (this.myForm.controls [key]) 当验证器是“必需”时正确获取值({required: true})但当它是另一个时,例如“min”返回 null
【解决方案2】:

刚刚清理/重构了上面的代码。创建作曲家函数 请看一下

// composer function
const composer = (control: FormControl, ...validators) => {
  control.setValidators(Validators.compose([...validators]));
}

for (let name of Object.keys(grp)) {
  let control = this.heroForm.controls[name];
  if (map.has(name)) {
    let validators = control.validator(control);
    if (validators && !validators.required) {
      let exisitingValidators = control.validators;
      composer(control, ...exisitingValidators, Validators.required);
    }
  }
}

【讨论】:

  • 感谢您的回复,一旦您有角度领域的解决方案,我会尝试优化,谢谢
  • 尚未实施。但你可以看到github.com/angular/angular/issues/13461
  • 顺便说一下,我不推荐使用 push(mutate state)。很难管理状态。做了一些修改,也许你可以试试这样的干净代码。
猜你喜欢
  • 2017-09-22
  • 2017-05-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
  • 2018-01-27
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多