What is the right way to create a FormArray of FormGroup in Angular?
I have the following:
component.ts:
export class DrawerContentComponent implements OnInit {
consumption = new FormGroup({
electricity: new FormControl(0),
water: new FormControl(0),
gas: new FormControl(0),
});
consumptionPerMonth = new FormArray([]);
ngOnInit() {
for (let index = 0; index < 12; index++) {
this.consumptionPerMonth.push(this.consumption);
}
}
showYearlyConsumption() {
console.log(this.consumptionPerMonth.value);
}
}
component.html:
<table>
<tr>
<th>Monat</th>
<th class="w-40">Stromverbrauch in kWh</th>
<th class="w-40">Wasserverbrauch in m³</th>
<th class="w-40">Gasverbrauch in kWh</th>
</tr>
<tr *ngFor="let month of consumptionPerMonth.controls; let i = index">
<ng-container [formGroup]="month">
<td>{{ i }}</td>
<td>
<input
class="border"
type="number"
[formControl]="month.controls.electricity"
/>
</td>
<td>
<input
class="border"
type="number"
[formControl]="month.controls.water"
/>
</td>
<td>
<input
class="border"
type="number"
[formControl]="month.controls.gas"
/>
</td>
</ng-container>
</tr>
</table>
<button (click)="showYearlyConsumption()">show</button>
When I fill for example on the website the first column of first row with 1, like this:
and click then on the "show" button then I have in console.log(this.consumptionPerMonth.value) on all 12 items the value of "electricity" = 1
like this:
console.log(this.consumptionPerMonth.value):
(12) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0
:
{electricity: 1, water: 0, gas: 0}
1
:
{electricity: 1, water: 0, gas: 0}
2
:
{electricity: 1, water: 0, gas: 0}
3
:
{electricity: 1, water: 0, gas: 0}
4
:
{electricity: 1, water: 0, gas: 0}
5
:
{electricity: 1, water: 0, gas: 0}
6
:
{electricity: 1, water: 0, gas: 0}
7
:
{electricity: 1, water: 0, gas: 0}
8
:
{electricity: 1, water: 0, gas: 0}
9
:
{electricity: 1, water: 0, gas: 0}
10
:
{electricity: 1, water: 0, gas: 0}
11
:
{electricity: 1, water: 0, gas: 0}
length
:
12
[[Prototype]]
:
Array(0)
What is the right way to do this, that I have in the "this.consumptionPerMonth.value" only in the first item a 1 for "electricity"?
You are passing the same instance of consumption
to the form array and end up actually with same control instance in the array. As of Angular 14 you can strongly type your forms so you can create an interface to describe the consumption like this:
interface Consumption {
electricity: FormControl<number | null>;
water: FormControl<number | null>;
gas: FormControl<number | null>;
}
Then initialize your consumptionPerMonth
field like this:
consumptionPerMonth = new FormArray<FormGroup<Consumption>>([]);
Finally in onInit
push a new instance of form group like this:
ngOnInit() {
for (let index = 0; index < 12; index++) {
this.consumptionPerMonth.push(new FormGroup({
electricity: new FormControl(0),
water: new FormControl(0),
gas: new FormControl(0),
}));
}
}
This should solve your issue and you will have strongly typed form which is much easier to work with.