web-dev-qa-db-ja.com

Angular2 FormControlオブジェクトから入力フィールドの名前を取得する方法は?

ReactiveFormsモジュールを使用してカスタムバリデーターを使用するフォームを管理するAngular 2アプリケーションがあります。バリデーターは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);
          });
    });
  }
24
Michael Oryl

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

これで、validator定義を調整する準備ができました。

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

.parent後で、["_parent"]

現時点では(today、now)、現在のリリースは次のとおりです。

2.1.2(2016-10-27)

しかし、この問題に続いて: feat(forms): 'parent'を 'AbstractControl'のパブリックプロパティにする

そして、すでにここで述べたように

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

特徴

  • フォーム: '親'を 'AbstractControl'のパブリックプロパティにする(#11855)(445e592)
  • ...

後で["_parent"].parentに変更できます

20
Radim Köhler

RadimKöhlerの答えを展開します。この関数を書く簡単な方法を次に示します。

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

Angular 4.2.xでは、public parentプロパティを使用してFormControlの親FormGroup(およびそのコントロール)にアクセスできます。 :

private formControl: FormControl;

//...

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

次の2つのオプションがあります。

Attributeデコレータの助けを借りて:

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

Inputデコレータの助けを借りて:

@Input() formControlName;

これを使用するには、検証がもちろんディレクティブである必要があります。

3
Bazinga

バリデーターにコントロール名を設定できます:

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

その後:

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

望みどおりではありませんが、いくつかの例のようにバリデーターを動的に作成できます。

のような

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

次に、フォームの作成時にバリデーターを使用して、次のようなコントロール名を渡します

0
dabicho