I'm attempting to calculate a total or other value based on a particular value in a FormArray.
I'm finding that when subscribing to valueChanges
and attempting to pass the whole array to something like reduce
, the "new value" isn't present on the parent FormGroup.
Original Example on StackBlitz
Sample:
this.frm.get('arr')['controls'][i].valueChanges
.subscribe((newVal) => {
this.frm.get('total').patchValue(
this.frm.get('arr').value.reduce((acc, curr) => {
return acc + curr.v;
}, 0)
)
});
If arr
has values [0, 1, 2, 3, 4]
and I change the first value to 1
, I still get 10
instead of 11
.
this.frm.get('arr').value
shows all the initial values and not the updated values.
I'm fairly new to Reactive Forms so I'm sure I'm just missing something fundamental here.
UPDATE (Have a solution, but I'm still lacking understanding):
I'd really love to know why I'm not able to subscribe to changes to the whole array like Eliseo had suggested.
I'm also interested in why there is such a difference between where I use .value
- If the whole point of Reactive Forms are to be Model Driven and then pass frm.value
to your Submit function, then why is .value
so inconsistent throughout the form hierarchy?
UPDATE 2
Updated StackBlitz Solution with guidance from Eliseo after his update
I've found a solution that I feel pretty good about. It doesn't use controls
anywhere and feels very clean. Eliseo's suggested approach pushed me to try this out. I believe the important thing is casting to a FormArray
and executing any push
on that. This keeps the parent
field tied to the rest of your FormGroup
or FormArray
thus it stays included in the valueChanges
event.
I now believe using controls
is an anti-pattern to Angular Reactive Forms, but I need to search for more guidance on that topic.
I got this to work.
Something about your form is a little strange. All 5 controls bind to the same
formControlName
"v". I think that may be the reason this form isn't acting the way you would like. The above does work, but adding thenewVal
on the end like this just seems odd.UPDATE:
This is working for all field changes.
Not the prettiest code I have ever seen, but it works. Get rid of the console logs, and it may be something you can live with. :)
why not listen changes of all array and make total with newValues?
That's not work, Change the code of buildForm for this:
The main changes is use forEach and not reduce, the use of parseInt, and the way to make the formArray.