angular - Hur får man namnet på ett inmatningsfält från ett Angular2 FormControl-objekt?


Jag har en Angular 2-applikation som använder ReactiveForms-modulen för att hantera ett formulär som använder en anpassad validator. Validatorn tar emot ett FormControl-objekt. Jag har några inmatningsfält som skulle kunna använda samma anpassade validator om jag bara visste namnet på fältet när FormControl skickades till validatorn.

Jag kan inte hitta någon metod eller publik egenskap på FormControl som exponerar inmatningsfältets namn. Det är förstås tillräckligt enkelt att se dess värde. Följande visar hur jag skulle vilja använda det:

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

Svar #1

För att utveckla Radim Köhlers svar. här är ett kortare sätt att skriva den funktionen.

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

Svar #2

Vi kan använda .parent-egenskapen, idag ["_parent"] (se mer nedan):

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

och nu är vi redo att justera vår validator-definition

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

.parent senare, ["_parent"] nu

För tillfället (idag, nu), aktuell version är :

2.1.2 (2016-10-27)

Men efter denna fråga: feat(forms): gör 'parent' till en offentlig egenskap hos 'AbstractControl'

Och som redan nämnts här

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

Funktioner

  • forms: gör 'parent' till en offentlig egenskap av 'AbstractControl' (#11855) (445e592)
  • ...

vi skulle senare kunna ändra ["_parent"] till .parent

Svar #3

Du kan ange kontrollnamn i validatorer:

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

Och sedan:

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

Relaterade artiklar