How not to use ngmodel for the FormArray? I'm trying to add my input fields but I'm using ngModel. Once you add row the value is passed to the next row.
.TS
this.form = this.formBuilder.group({
id : [0],
Status: ['', Validators.required],
array: this.formBuilder.array([this.createList()])
})
createList(): FormGroup {
return this.formBuilder.group({
id: [0],
QtyOrder : ['0', Validators.required],
QtyDelivered : [''],
QtyRejected : ['', Validators.required],
QtyReceived : ['', Validators.required],
})
}
get array():FormArray{
return this.form.get('array') as FormArray;
}
Calculate(){
let total = this.form.get('array') as FormArray;
return total.controls.map((x) => x.get('QtyDelivered').value - x.get('QtyRejected').value).reduce((sum,amount) => sum amount, 0);
}
.HTML ----Here I want to put the total.---
<input type="text" formControlName="QtyReceived" [ngModel]="Calculate()">
CodePudding user response:
You can add events for when the QtyDelivered
and QtyRejected
controls are key in with value, it will trigger the Calculate()
method.
<input formControlName="QtyDelivered" (input)="Calculate()" />
<input formControlName="QtyRejected" (input)="Calculate()" />
And modify the Calculate
method to bind the calculated value to QtyReceived
control.
Calculate() {
let total = this.form.get('array') as FormArray;
total.controls[0]
.get('QtyReceived')
.patchValue(
total.controls
.map((x) => x.get('QtyDelivered').value - x.get('QtyRejected').value)
.reduce((sum, amount) => sum amount, 0)
);
}
Note that you are performing the calculation for all FormGroup in FormArray, it is fine when you have only one FormGroup in FormArray, but if you are trying to perform the calculation for each row (when there is more than one FormGroup in FormArray), the calculation is incorrect.
In case you are performing the calculation by row, you need to specify the FormGroup to be used for calculation.
Solution 1: Trigger with (input)
event.
<input formControlName="QtyDelivered" (input)="Calculate(i)" />
<input formControlName="QtyRejected" (input)="Calculate(i)" />
Calculate(i) {
let total = this.form.get('array') as FormArray;
let formGroup = total.controls[i] as FormGroup;
formGroup
.get('QtyReceived')
.patchValue(
formGroup.get('QtyDelivered').value - formGroup.get('QtyRejected').value
);
}
Sample StackBlitz Demo (Solution 1)
Solution 2: Subscribe FormControl valueChanges event.
this.array.controls.forEach((g: FormGroup) => {
g.get('QtyDelivered')
.valueChanges.pipe(debounceTime(500))
.subscribe((x) => {
g.get('QtyReceived').patchValue(this.Calculate(g));
});
g.get('QtyRejected')
.valueChanges.pipe(debounceTime(500))
.subscribe((x) => {
g.get('QtyReceived').patchValue(this.Calculate(g));
});
});
Calculate(formGroup: FormGroup) {
return (
formGroup.get('QtyDelivered').value - formGroup.get('QtyRejected').value
);
}
Sample StackBlitz Demo (Solution 2)
Make sure that you have to unsubscribe the observable for valueChanges
when the component is destroyed for better optimization.