web-dev-qa-db-ja.com

AngularのカスタムフォームコンポーネントからFormControlへのアクセスを取得します

Angularアプリケーションには、ControlValueAccessorインターフェイスを実装するカスタムフォームコントロールコンポーネントがあります。

ただし、コンポーネントに関連付けられているFormControlインスタンスにアクセスします。 FormBuilderでリアクティブフォームを使用し、formControlName属性を使用してフォームコントロールを提供しています。

SO、カスタムフォームコンポーネント内からFormControlインスタンスにアクセスするにはどうすればよいですか?

41
Slava Fomin II

このソリューションは、Angularリポジトリの ディスカッション から生まれました。この問題に興味がある場合は、必ずそれを読むか、参加してください。


私はFormControlNameディレクティブのコードを研究しましたが、次のソリューションを書くようになりました。

@Component({
  selector: 'my-custom-form-component',
  templateUrl: './custom-form-component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: CustomFormComponent,
    multi: true
  }]
})
export class CustomFormComponent implements ControlValueAccessor, OnInit {

  @Input() formControlName: string;

  private control: AbstractControl;


  constructor (
    @Optional() @Host() @SkipSelf()
    private controlContainer: ControlContainer
  ) {
  }


  ngOnInit () {

    if (this.controlContainer) {
      if (this.formControlName) {
        this.control = this.controlContainer.control.get(this.formControlName);
      } else {
        console.warn('Missing FormControlName directive from Host element of the component');
      }
    } else {
      console.warn('Can\'t find parent FormGroup directive');
    }

  }

}

親にFormGroupをコンポーネントに注入し、FormControlバインディングを通じて取得したコントロール名を使用して、特定のformControlNameをコンポーネントから取得しています。

ただし、このソリューションはHost要素でFormControlNameディレクティブが使用されるユースケース専用に調整されていることに注意してください。他の場合には機能しません。このために、いくつかの追加ロジックを追加する必要があります。これがAngularによって対処されるべきだと思う場合は、必ず ディスカッション にアクセスしてください。

43
Slava Fomin II

[formControl]ディレクティブを介してバインドする場合、formControlNameを入力パラメーターとして使用しても機能しません。

入力パラメーターなしで両方の方法で機能するソリューションを次に示します。

export class MyComponent implements AfterViewInit {

  private control: FormControl;

  constructor(
    private injector: Injector,
  ) { }

  // The form control is only set after initialization
  ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      this.control = ngControl.control as FormControl;
    } else {
      // Component is missing form control binding
    }
  }
}
27
Randy

@Riteshがすでにコメントに書いているように、フォームコントロールを入力バインディングとして渡すことができます。

<my-custom-form-component [control]="myForm.get('myField')" formControlName="myField">
</my-custom-form-component>

そして、次のようにカスタムフォームコンポーネント内でフォームコントロールインスタンスを取得できます。

@Input() control: FormControl;
3
Yuri Beliakov

Angular 6/7 +で2019年にここに来る人にとって、非推奨の警告をスローしないソリューションは、この回答で説明されているものです。

https://stackoverflow.com/a/56061527/13412

詳細については、上記のように このプレゼンテーション をご覧ください。

2
AsGoodAsItGets