Angularのリアクティブフォームではtsファイル側でネストした構成を組むことができます。
HTMLファイルでもformGroupやformControlの名前を定義できるのですが、
tsファイルで定義した構成に合うようにしてあげる必要があります。
構成に誤りがあると、以下のようなエラーが出たりします。
ERROR Error: formControlName must be used with a parent formGroup directive. You'll want to add a formGroup directive and pass it an existing FormGroup instance (you can create one in your class).
それでは例で見てみましょう。
htmlで構成を再現する
formGroupName、formControlName、formArrayNameの3種類をうまく使って構成を組み上げてあげましょう。
それぞれFormControl、 FormGroup、FormArrayにNameがついただけなのでわかりやすいですね。
例えば、tsファイルで以下のような構成で組んだ場合。
~~
formGroup: FormGroup;
roomMates: Array;
constructor( private fb: FormBuilder ){}
ngOnInit() {
this.formGroup = this.fb.group({
firstName: [''],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['111-1111']
}),
frends: this.fb.array([
this.fb.control(''),
this.fb.control('')
])
});
}
テキストボックスではhtml側では以下のように書けばOKです。
<form [formGroup]="formGroup">
<input type="text" formControlName="firstName"> // tsファイルでfirstNameとして設定したformControlと紐付け。
<input type="text" formControlName="lastName">
<div formGroupName="address"> // tsファイルでaddressと設定したformGroupと紐付け。
<input type="text" formControlName="street"> // ネストしたformControlはformGroupNameを設定した要素の中に配置
<input type="text" formControlName="city">
<input type="text" formControlName="state">
<input type="text" formControlName="zip">
</div>
<div formArrayName="friends">
<div *ngFor="let roomMate of roomMates; index as i" >
<input type="text" formControlName="{{i}}">
</div>
</div>
</form>
なお、tsファイル側だけで設定するということもあると思いますが、
html側にformControlNameが足りなくてもエラーになりません。
formArrayNameやformGroupNameが足りなくとどうなるか知りませんが、多分エラーにならないと思います。
コンポーネントを分割した場合
子コンポーネントに切り分けてあげる場合、親と同等に構造を書いてあげる必要があります。
上記の例のaddressの中を分割したとします。
<form [formGroup]="formGroup">
<input type="text" formControlName="firstName">
<input type="text" formControlName="lastName">
<div formGroupName="address">
<app-address-area [formGroup]="formGroup"></app-address-area> // address内をコンポーネント分割してformGroupを渡す。
</div>
<div formArrayName="friends">
<div *ngFor="let roomMate of roomMates; index as i" >
<input type="text" formControlName="{{i}}">
</div>
</div>
</form>
この場合、子コンポーネントでは以下のように書けばOKです。
<form [formGroup]="formGroup">
<div formGroupName="address">
<input type="text" formControlName="street">
<input type="text" formControlName="city">
<input type="text" formControlName="state">
<input type="text" formControlName="zip">
</div>
</form>
普通はformGroupName=”address”ごと分割する方が良いですが、
多少わかり安いかなと思い上記のように書いてみました。







