a brief explain about FormArrays
If we want an object like
[
{status:'status 1',description:'description 1'},
{status:'status 2',description:'description 2'},
{status:'status 3',description:'description 3'},
...
]
We has an array of object, so we need a FormArray of FormGroups (*). To create it's usefull has a function that return a FormGroup (one element of the FormArray)
createGroup():FormGroup
{
return new FormGroup({
status:new FormControl(),
description:new FormControl(),
})
}
If our FormArray belongs to a FormGroup, it's usefull has a getter function that return our FormArray
form:FormGroup; //<--declare the form
get statusArray():FormArray
{
return this.form.get('emp_status') as FormArray
}
//in ngOnInit
ngOnInit()
{
this.form=new FormGroup({
other_property:new FormControl(),
emp_status=new FormArray([]) //<--see that we create an empty FormArray
})
}
If only want the FormArray itself only declare
formArray:FormArray
//in ngOnInit we create the formArray empty -well you can do it in the declaration-
ngOnInit()
{
this.formArray=new FormArray([]) //<--see that we create an empty FormArray
}
Now we are going to add elements to the array. Remember that each element of the FormArray is a FormGroup, but we has a function that return a formGroup!
So, we can add simply using
this.statusArray.push(this.createGroup()) //if we are using a formArray inside a FormGroup
this.formArray.push(this.createGroup()) //if we has the formarray standalone
If we want add the formArray based in an array, we usually "map" the array to a FormGroup and create the array, puff. Imagine you has an array of data, you can do
this.form=new FormGroup({
other_property:new FormControl(),
emp_status=new FormArray(
this.data.map(x=>this.createGroup()) //<--each element of this data
//like a formGroup
)
})
//or with our standalone FormArray
this.formArray=new FormArray(this.data.map(x=>this.createGroup()))
Well, to see in .html
First check if it's all ok
<pre>
{{form?.value|json}}
</pre>
//or
<pre>
{{formArray.value|json}}
</pre>
we are using inputs and divs
if is in a FormGroup
<form [formGroup]="form">
<!--say to Angular we are going to use the formArray using formArrayName-->
<div formArrayName="emp_status">
<!--iterate over the controls of formArray and use [formGroupName]-->
<!--see that we use our getter function-->
<div *ngFor="let group of statusArray.controls;let i=index" [formGroupName]="i">
<!--use formControlName, we are yet in a formGroup-->
<input formControlName="status">
<input formControlName="description">
</div>
</div>
</form>
If the FormArray is standalone there are a problem with the strict mode. before we can use
/**BEFORE***/
<div *ngFor="let group of formArray.controls;let i=index" [formGroup]="group">
Now, we create an auxiliar function
getGroupAt(index)
{
return this.formArray.at(index) as FormGroup
}
<form [formGroup]="formArray">
<!--iterate over the controls of formArray and use [formGroup]-->
<div *ngFor="let group of formArray.controls;let i=index" [formGroup]="getGroupAt(i)">
<!--use formControlName, we are yet in a formGroup-->
<input formControlName="status">
<input formControlName="description">
</div>
</div>
</form>
You can see in stackblitz
Updated how populate the array data given
Remember when we write this.formArray=new FormArray(this.data.map(x=>this.createGroup())) ?
What about write
this.formArray=new FormArray(this.data.map(x=>this.createGroup(x)))
?
Well, change the funciton createGroup for some like
createGroup(data:any=null):FormGroup
{
data=data || {status:null,description:null}
return new FormGroup({
status:new FormControl(data.status),
description:new FormControl(data.description),
})
}
END
(*) a FormArray can be a FormArray of FormControls if we want to manage only an array of numbers or an array of strings
emp_statuslike<form [formGroup]="emp_status"></form>