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

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-02 20:23:57

To expand on Radim Köhler answer. 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):

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

At the moment (today, now), current release is :

2.1.2 (2016-10-27)

But following this issue: feat(forms): make 'parent' a public property of 'AbstractControl'

And as already stated here

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

Features

  • forms: make 'parent' a public property of 'AbstractControl' (#11855) (445e592)
  • ...

we could later change the ["_parent"] into .parent

You have two options:

With the help of the Attribute decorator:

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

With the help of the Input decorator:

@Input() formControlName;

To use this your validation needs to be a directive of course.

As of Angular 4.2.x, you can access a FormControl's parent FormGroup (and its controls) using the public parent property:

private formControl: FormControl;

//...

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!