angular2で1つの大きなフォームを作りたいと思っています。しかし、次の例のように複数のコンポーネントでこのフォームを作りたいのです。
アプリコンポーネント
<form novalidate #form1="ngForm" [formGroup]="myForm">
<div>
<address></address>
</div>
<div>
<input type="text" ngModel required/>
</div>
<input type="submit" [disabled]="!form1.form.valid" > </form>
アドレスコンポーネント
<div>
<input type="text" ngModel required/> </div>
上記のコードを使用したところ、ブラウザ上では正常に表示されましたが、addressコンポーネントのテキストを削除すると、送信ボタンが無効になりません。 しかし、appコンポーネントの入力ボックスのテキストを削除すると、ボタンは正しく無効化されました。
私は、かなりきれいに機能するリアクティブフォームを使用します。そして、あなたのコメントについて。
他に簡単な例はないのでしょうか?たぶん、ループのない同じ例
例を挙げましょう。必要なのは、FormGroup
をネストして、それを子に渡すだけです。
例えば、あなたのフォームがこのようなもので、 address
フォームグループを子に渡したいのだとします。
ngOnInit() {
this.myForm = this.fb.group({
name: [''],
address: this.fb.group({ // create nested formgroup to pass to child
street: [''],
zip: ['']
})
})
}
そして親フォームでは、ネストしたフォームグループを渡すだけです。
<address [address]="myForm.get('address')"></address>
子プロセスでは、ネストされたフォームグループに @Input
を使用します。
@Input() address: FormGroup;
そして、テンプレートでは [formGroup]
を使用します。
<div [formGroup]="address">
<input formControlName="street">
<input formControlName="zip">
</div>
もし、実際にネストしたフォームグループを作りたくない場合は、そのようなことをする必要はありません。
this.myForm = this.fb.group({
name: [''],
street: [''],
zip: ['']
})
のようにすれば、好きなコントロールを渡すことができます。上記と同じ例で、street
とzip
だけを表示したい場合、子コンポーネントはそのままで、テンプレート内の子タグは以下のようになります。
<address [address]="myForm"></address>
以下は
ネストされたモデル駆動型フォームについての詳細は こちらを参照してください。
私の経験上、テンプレート駆動型のフォームでは、このようなフォームフィールドの構成は難しいです。アドレスコンポーネントに埋め込まれたフィールドは、フォーム(NgForm.controlsオブジェクト)に登録されないので、フォームのバリデーションの際に考慮されないのです。
私の場合、この方法でうまくいったので紹介します。以下のようなディレクティブを作成しました。
import { Directive } from '@angular/core';
import { ControlContainer, NgForm } from '@angular/forms';
@Directive({
selector: '[appUseParentForm]',
providers: [
{
provide: ControlContainer,
useFactory: function (form: NgForm) {
return form;
},
deps: [NgForm]
}
]
})
export class UseParentFormDirective {
}
このディレクティブを、例えば子コンポーネントで使用する場合。
<address app-use-parent-form></address>
のようにすると、AddressComponentのコントロールがform1に追加されます。その結果、フォームの有効性は、子コンポーネント内のコントロールの状態にも依存することになります。
Angular 6 のみで確認