如何从Angular2 FormControl对象获取输入字段的名称?

时间:2016-11-01 14:11:18

标签: angular typescript angular2-forms angular-forms

我有一个Angular 2应用程序,它使用ReactiveForms模块来管理使用自定义验证程序的表单。验证器接收FormControl个对象。我有一些输入字段可以使用相同的自定义验证器,只要我知道FormControl传递给验证器时字段的名称。

我无法在FormControl上找到任何公开输入字段名称的方法或公共属性。当然,它很容易看到它的价值。以下显示了我想如何使用它:

public asyncValidator(control: FormControl): {[key: string]: any} {
  var theFieldName = control.someMethodOfGettingTheName(); // this is the missing piece

  return new Promise(resolve => {
      this.myService.getValidation(theFieldName, control.value)
        .subscribe(
          data => {
            console.log('Validation success:', data);
            resolve(null);
          },
          err => {
            console.log('Validation failure:', err);
            resolve(err._body);
          });
    });
  }

6 个答案:

答案 0 :(得分:20)

我们今天可以使用 .parent 属性["_parent"] (请参阅下文)

export const getControlName = (control: ng.forms.AbstractControl) =>
{
    var controlName = null;
    var parent = control["_parent"];

    // only such parent, which is FormGroup, has a dictionary 
    // with control-names as a key and a form-control as a value
    if (parent instanceof ng.forms.FormGroup)
    {
        // now we will iterate those keys (i.e. names of controls)
        Object.keys(parent.controls).forEach((name) =>
        {
            // and compare the passed control and 
            // a child control of a parent - with provided name (we iterate them all)
            if (control === parent.controls[name])
            {
                // both are same: control passed to Validator
                //  and this child - are the same references
                controlName = name;
            }
        });
    }
    // we either found a name or simply return null
    return controlName;
}

现在我们已准备好调整验证器定义

public asyncValidator(control: FormControl): {[key: string]: any} {
  //var theFieldName = control.someMethodOfGettingTheName(); // this is the missing piece
  var theFieldName = getControlName(control); 
  ...

.parent之后,["_parent"]现在

目前(今天,现在),当前版本是:

2.1.2 (2016-10-27)

但请关注此问题:feat(forms): make 'parent' a public property of 'AbstractControl'

如前所述

2.2.0-beta.0 (2016-10-20)

  

功能

     
      
  • 形式:让'parent'成为'AbstractControl'的公共财产(#11855)(445e592)
  •   
  • ...
  •   

我们稍后可以将["_parent"]更改为.parent

答案 1 :(得分:17)

扩展RadimKöhler的答案。这是编写该功能的一种较短的方式。

getControlName(c: AbstractControl): string | null {
    const formGroup = c.parent.controls;
    return Object.keys(formGroup).find(name => c === formGroup[name]) || null;
}

答案 2 :(得分:3)

您有两种选择:

借助Attribute装饰者:

constructor(@Attribute('formControlName') public formControlName) {}

借助Input装饰者:

@Input() formControlName;

要使用此功能,您的验证当然需要是指令。

答案 3 :(得分:3)

从Angular 4.2.x开始,您可以使用公共属性访问FormControl的父FormGroup(及其控件):

private formControl: FormControl;

//...

Object.keys(this.formControl.parent.controls).forEach((key: string) => {
  // ...
});

答案 4 :(得分:1)

您可以在验证器中设置控件名称:

    this.form = this.fb.group({
        controlName:      ['', [Validators.required, (c) => this.validate(c, 'controlName')]]
    });

然后:

validate(c: FormControl, name) {
    return name === 'controlName' ? {invalid: true} : null;
}

答案 5 :(得分:0)

不完全是您想要的,但您可以像在某些示例中那样动态创建验证器。

typeBasedValidator(controlName: string): ValidatorFn {
  return(control: AbstractControl): {[key: string]: any} => {
     // Your code using controlName to validate
     if(controlName == "something") { 
       doSomething(); 
     } else { 
       doSomethingElse(); 
     }
  }
}

然后在创建表单时使用验证器,传递控件名称 像