Angularアプリケーションには、ControlValueAccessor
インターフェイスを実装するカスタムフォームコントロールコンポーネントがあります。
ただし、コンポーネントに関連付けられているFormControl
インスタンスにアクセスします。 FormBuilder
でリアクティブフォームを使用し、formControlName
属性を使用してフォームコントロールを提供しています。
SO、カスタムフォームコンポーネント内からFormControl
インスタンスにアクセスするにはどうすればよいですか?
このソリューションは、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によって対処されるべきだと思う場合は、必ず ディスカッション にアクセスしてください。
[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
}
}
}
@Riteshがすでにコメントに書いているように、フォームコントロールを入力バインディングとして渡すことができます。
<my-custom-form-component [control]="myForm.get('myField')" formControlName="myField">
</my-custom-form-component>
そして、次のようにカスタムフォームコンポーネント内でフォームコントロールインスタンスを取得できます。
@Input() control: FormControl;
Angular 6/7 +で2019年にここに来る人にとって、非推奨の警告をスローしないソリューションは、この回答で説明されているものです。
https://stackoverflow.com/a/56061527/13412
詳細については、上記のように このプレゼンテーション をご覧ください。