FormGroup inside FormArray in Angular 2 Reactive Forms
You can move formArrayName inline with *ngFor and include .controls in ngFor, as we are looping the form controls.
<div>
<div formArrayName="order_lines" *ngFor="let line of orderForm.get('order_lines').controls; let i=index">
<div [formGroupName]="i">
<input type="text" [formControlName]="product_id">
<input type="text" [formControlName]="description">
<input type="number" [formControlName]="units">
<input type="number" [formControlName]="unit_price">
<input type="number" [formControlName]="line_total">
</div>
</div>
</div>
@Johna, to complementary my answer:
You have two functions
buildForm(data:any):FormGroup
{
return data?this.fb.group({
id: [data.id?data.id:''],
store: [data.store?data.store:'', Validators.required],
order_lines:this.fb.array(this.buildArrayControl(data.order_lines?data.order_lines:null))
})
:
this.fb.group({
id: [''],
store: ['', Validators.required],
order_lines:this.fb.array(this.buildArrayControl(null))
})
}
buildArrayControl(data:any[]|null):FormGroup[]
{
return data?
data.map(x=>{
return this.fb.group({
id: [x.id?x.id:''],
order_id: [x.order_id?x.order_id:''],
product_id: [x.product_id?x.product_id:''],
description: [x.description?x.description:'', Validators.required],
unit_price: [x.unit_price?x.unit_price:'', Validators.required],
discount: [x.discount?x.discount:0],
units: [x.units?x.units:1, Validators.required],
line_total: [x.line_total?x.line_total:'', Validators.required]
})
})
:
[this.fb.group({
id: [''],
order_id: [],
product_id: [],
description: ['', Validators.required],
unit_price: ['', Validators.required],
discount: [0],
units: [1, Validators.required],
line_total: ['', Validators.required]
})
]
}
then you can do, e.g.
this.orderForm = this.buildForm(
{
id:'112',
store:'22655',
order_lines:[{description:1222,....},{description:1455,...}]
}
)
//or
this.orderForm=this.buildForm(null);
Instead of using form.get
better to go with controls like below -
<form [formGroup]="orderForm">
<input type="number" formControlName="id">
<input type="text" formControlName="store">
<div formArrayName="order_lines">
<div *ngFor="let line of orderForm.controls.order_lines.controls; let i=index">
<div [formGroupName]="i">
<input type="text" formControlName="product_id">
<input type="text" formControlName="description">
<input type="number" formControlName="units">
<input type="number" formControlName="unit_price">
<input type="number" formControlName="line_total">
</div>
</div>
</div>
</form>
Working Example
What you are missing -
- you are missing
.control
in last of *ngFor to iterate over the controls. - If you are using above approach you need to replace
[formControlName]
withformControlName