【问题标题】:Angular2: Find out if FormControl has required validator?Angular2:找出 FormControl 是否需要验证器?
【发布时间】:2017-02-10 15:52:15
【问题描述】:

如果为控件注册了所需的验证器,是否有人知道找到 Angular2 FormControl 的方法。

this.form = builder.group({name: ['', Validators.required]};

如果是必填字段,我可以查询this.form.controls['name'] 控件吗?我知道我可以检查它是否有效,但这不是我想要的。

亲切的问候, 马克

【问题讨论】:

  • 您找到解决问题的方法了吗?
  • @marc 你找到解决方案了吗?我最接近的是使用 AbstractControl 或 FormControl 的“getError()”方法,但它在生命周期中填充得太晚了。
  • 我还需要一些解决方案来解决这种情况。 (知道是否需要一个表单字段而不进行验证,只知道是否需要,有值或无值),你找到解决方案了吗?

标签: angular forms typescript validation


【解决方案1】:

我不知道检查控件是否需要验证器的确切方法是什么。

但解决方法可能是这样, 每当控件需要验证器时,它都会向该控件添加 validator() 函数。

例如。

<input type="text" formControlName="firstname">

constructor(private formBuilder: FormBuilder){
    this.registerForm = this.formBuilder.group({
        firstname: ['', Validators.required]     //<<<===one required validation on firstname control
    });

    console.log(this.registerForm.controls.firstname.validator.length);
                                                 //<<<===this will return 1.
   });

}

在上面的代码中,验证器的长度是一(1)


  console.log(this.registerForm.controls.firstname.validator.length);
                                                 //this will return exception

这一行将返回一个。如果没有附加验证器,那么名字将没有验证器()函数,所以在这种情况下我会给出一个例外。

演示:https://plnkr.co/edit/I7b5JNAavmCJ6Py1eQRr?p=preview

【讨论】:

  • 这只会告诉你是否存在验证器,而不是它是否是专门要求的验证器,这是 OP 所要求的。
【解决方案2】:

我也有类似的问题。目前,我正在使用这个:

  import { Attribute } from '@angular/core';

  // "Kind-of" hack to allow "pass-through" of the required attribute
  constructor(@Attribute('required') public required) {
    // call super here if the component is an ancestor
  }

我真的很困惑为什么像“禁用”这样的属性包含在 FormControl 中,而不是“必需”。

【讨论】:

  • 因为 require 在表单 API 中没有特殊含义,它就像任何可能的错误一样。如果您要创建一个特殊的验证器来填充 error 属性 notABanana 您不会希望在 AC 上使用它,对吗?我确实认为我们需要方法来访问给定 AC 上的当前验证器。
【解决方案3】:

执行此操作的一种方法是在加载表单时检查控件是否有效,以查看它是否具有所需的错误(如果字段为空,则会出现该错误)。

这不适用于其他验证器,例如 minLength,因为在控件更改之前它们不会被触发

export class FormInputComponent implements Field, OnInit {
  private _required: boolean;
  config: FieldConfig;
  group: FormGroup;

    /** Readonly properties. */
  get required(): boolean { 
    return this._required;
  }

  ngOnInit() {
    var _validator: any = this.group.controls[this.config.name].validator && this.group.controls[this.config.name].validator(this.group.controls[this.config.name]);
    this._required = _validator && _validator.required;
  }
}

【讨论】:

  • 不是一个很好的解决方案,因为输入可能会在 init 上填充一个值。
【解决方案4】:

没有办法检查验证器或获取所有验证器:https://github.com/angular/angular/issues/13461

@fairlie-agile 解决方案非常聪明。但我认为我们必须使用空的 FormControl,因为我们需要触发所需的验证器,并且 this.group.controls[this.config.name] 可能已经用一些值进行了初始化。

ngOnInit() {
    let formControl = this.group.controls[this.config.name];
    let errors: any = formControl.validator && formControl.validator(new FormControl());
    this._required = errors !== null && errors.required;
}

【讨论】:

    【解决方案5】:

    虽然没有 Angular API 可以直接查找是否为特定字段设置了 required 验证器,但实现此目的的迂回方式如下:

    import { NgForm, FormControl } from '@angular/forms';
    
    const isRequiredControl = (formGroup: NgForm, controlName: string): boolean => {
        const { controls } = formGroup
        const control = controls[controlName]
        const { validator } = control
        if (validator) {
            const validation = validator(new FormControl())
            return validation !== null && validation.required === true
        }
        return false
    }
    

    我已经对此进行了测试,并且仅当将 Validator.Required 验证器添加到特定的 FormControl 时才会触发。

    【讨论】:

      【解决方案6】:

      这个函数应该适用于 FormGroups 和 FormControls

        export const hasRequiredField = (abstractControl: AbstractControl): boolean => {
          if (abstractControl.validator) {
              const validator = abstractControl.validator({}as AbstractControl);
              if (validator && validator.required) {
                  return true;
              }
          }
          if (abstractControl['controls']) {
              for (const controlName in abstractControl['controls']) {
                  if (abstractControl['controls'][controlName]) {
                      if (hasRequiredField(abstractControl['controls'][controlName])) {
                          return true;
                      }
                  }
              }
          }
          return false;
      };
      

      【讨论】:

      • 这应该是公认的答案。效果很好,非常感谢!
      • 我被第 3 行弄糊涂了,直到今天再看一遍。所以验证器函数是暴露的,可以在任何控件上调用;你在一个伪装成控件的空对象上调用它。知道了。我的问题:为什么这只适用于所需的验证器?我在一个只有 minLength 验证器的字段上尝试了这个,结果对象是空的。这个技巧可以用来检查除必需之外的任何东西吗?
      • 它只适用于这个 Angular 版本中的 required-validator,认为它是 v4。注意到和你一样的东西。
      • @MarcelTinner - 以下是如何以良好性能实施解决方案的要点:gist.github.com/jsdevtom/5589af349a395b37e699b67417ef025b
      • abstractControl.validator 不是 AbstractControl 类型的函数,它将如何工作
      【解决方案7】:

      假设最初注册的唯一错误是required 错误

      // in your component you'll have access to `this.myFormGroup`
      const formGroup = {
        controls: {
          email: {
            errors: {
              required: true
            }
          },
          username: {
            errors: null
          }    
        }
      }
      
      // required by default
      let required = {
        email: '*',
        username: '*',
      };
      
      // in `ngOnInit`
      required = Object.entries(formGroup.controls)
        .map(([key, control]) => [key, control.errors])
        .filter(([, errors]) => !errors)
        .map(([key]) => [key, ''])
        .reduce((_required, [key, isRequired]) => Object.assign(_required, { [key]: isRequired }), required)
      
      // in your template you may write `<label>Email{{ required.email }}</label>`
      console.log(required)

      【讨论】:

        【解决方案8】:

        我用这个解决了一个类似的问题:

        get lastPriceField(): AbstractControl {
            return this.form.get('last_price');
        }
        
        private checkIfFieldHasValidatorRequired() {    
            const validators = (this.lastPriceField as any)._rawValidators;
            this._lastPriceIsRequired = validators && validators.some(item => item.name === "required");
        }
        

        【讨论】:

          【解决方案9】:

          一个简短的版本。 首先,创建一个空控件,避免在方法中不断地做。

            private readonly emptyFormControl = new FormControl();
          

          然后检查方法。如果控件已启用并且其验证器在验证空控件时出现“必需”错误,则该控件是强制性的。

            private isMandatory = (fc: FormControl): boolean =>
              fc.enabled && !!fc.validator && !!fc.validator(this.emptyFormControl)?.required;
          

          这仅适用于 FormControl 对象。如果需要支持FormGroup或/和FormArray,需要在检查方法中加入递归。

          【讨论】:

            【解决方案10】:

            Angular 现在提供hasValidator,您可以使用它检查表单控件是否具有同步验证器。如果您碰巧需要检查它是否有异步验证器,hasAsyncValidator 也存在。

            如果您想检查是否需要表单控件,您可以这样做:

            this.form.get('name').hasValidator(Validators.required);
            

            【讨论】:

              猜你喜欢
              • 2016-02-25
              • 2018-07-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-11-13
              • 1970-01-01
              • 2019-10-10
              • 2017-09-20
              相关资源
              最近更新 更多