简体   繁体   English

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

[英]How to get name of input field from Angular2 FormControl object?

I have an Angular 2 application that uses the ReactiveForms module to manage a form that uses a custom validator.我有一个 Angular 2 应用程序,它使用ReactiveForms模块来管理使用自定义验证器的表单。 The validator receives a FormControl object.验证器接收一个FormControl对象。 I have a few input fields that could use the same custom validator if only I knew the name of the field when the FormControl was passed to the validator.我有几个输入字段可以使用相同的自定义验证器,前提是我在将FormControl传递给验证器时知道字段的名称。

I can't find any method or public property on FormControl that exposes the input field's name.我在FormControl上找不到任何公开输入字段名称的方法或公共属性。 It's simple enough to see its value, of course.当然,很简单就能看出它的价值。 The following shows how I would like to use it:下面显示了我想如何使用它:

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

To expand on Radim Köhler answer.扩展 Radim Köhler 的答案。 here is a shorter way of writing that function.这是编写该函数的较短方法。

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

We can use .parent property, well today ["_parent"] (see more below) :我们可以使用.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;
}

and now we are ready to adjust our validator definition现在我们准备调整我们的验证器定义

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

.parent later, ["_parent"] now .parent以后, ["_parent"]现在

At the moment (today, now) , current release is :目前(今天,现在) ,当前版本是:

2.1.2 (2016-10-27) 2.1.2 (2016-10-27)

But following this issue: feat(forms): make 'parent' a public property of 'AbstractControl'但是在这个问题之后: feat(forms): make 'parent' a public property of 'AbstractControl'

And as already stated here正如这里已经说明的那样

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

Features特点

  • forms: make 'parent' a public property of 'AbstractControl' (#11855) (445e592)表单:使 'parent' 成为 'AbstractControl' 的公共属性 (#11855) (445e592)
  • ... ...

we could later change the ["_parent"] into .parent我们可以稍后将["_parent"]更改为.parent

As of Angular 4.2.x, you can access a FormControl 's parent FormGroup (and its controls) using the public parent property:从 Angular 4.2.x 开始,您可以使用公共属性访问FormControl的父FormGroup (及其控件):

private formControl: FormControl;

//...

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

You have two options:您有两个选择:

With the help of the Attribute decorator:Attribute装饰器的帮助下:

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

With the help of the Input decorator:Input装饰器的帮助下:

@Input() formControlName;

To use this your validation needs to be a directive of course.要使用它,您的验证当然需要是一个指令。

You can set control name in validators:您可以在验证器中设置控件名称:

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

And then:然后:

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

Not exactly what you want but you could dynamically create the validator like in some examples.不完全是您想要的,但您可以像某些示例中那样动态创建验证器。

like喜欢

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

Then use the validator when creating the form, passing the control name like然后在创建表单时使用验证器,传递控件名称,如

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM