mhfour
mhfour

Reputation: 265

Get total in FormArray Angular 8

I would like to get the values of an input in each row and get the sum of these rows.

my HTML:

<ng-container formArrayName="cap_values">
    <tbody *ngFor="let item of capValues.controls; let i=index" [formGroupName]="i">
        <tr>
            <td class="freeze-first-col"><input type="text" (blur)="getName(item.value.name)" formControlName="name"></td>
            <td><input type="number" formControlName="fdnTotalShares"</td>
        </tr>
    </tbody>
</ng-container>

my .ts:

ngOnInit() {
  this.form = this.fb.group({
    cap_values: this.fb.array([this.fb.group({
      name: '',
      fdnTotalShares: '',
    }
    )])
  })
}

How do I iterate over each value in the array and sum it? I have seen .valueChanges but am not entirely sure how to use it.

Upvotes: 1

Views: 5942

Answers (4)

miselking
miselking

Reputation: 3083

There are multiple ways you can do this, I'll write down some:

1st way:

get capValues(): FormArray {
    return this.form.get('cap_values') as FormArray;
}

getSum() {
    this.sum = this.capValues.value.reduce((prev, next) => prev + +next.fdnTotalShares, 0);
    // OR
    // this.sum = this.capValues.getRawValue().reduce((prev, next) => prev + +next.fdnTotalShares, 0);
}

Notice the + sign in +next.fdnTotalShares, that is not a mistake, it is to make sure that you get the sum of numbers (assuming fdnTotalShares will always be a number) instead of getting string concatenation.

2nd way:

this.sum = 0;
this.capValues.value.forEach(x => {
      this.sum += +x.fdnTotalShares;
});

Instead of value you can use getRawValue() if you have some controls that are disabled and you want to include them in your calculation.

Here is a stackblitz example demonstrating this (I also included the difference with enabled and disabled controls).

EDIT: To answer you question in the comment, this is similar as the sum example I wrote above:

multiplyAndStore() {
    const multiplicationRes = this.capValues.value.reduce((prev, next) => prev * +next.fdnTotalShares, 1);
    // Assuming that "formControlName" for multiplication result input is 'multiplyResult'
    this.form.get('multiplyResult').setValue(multiplicationRes);
    // You can also use "patchValue" method instead of "setValue"
    // this.form.get('multiplyResult').patchValue(multiplicationRes);
}

I have updated the stackblitz example so you can see this in action.

Hope this helps.

Upvotes: 6

nash11
nash11

Reputation: 8660

Use the valueChanges Observable to achieve this.

In your component, once you create your form, subscribe to the valueChanges in your form array cap_values.

import { Subscription } from 'rxjs';

total: number = 0;
subscription: Subscription;

ngOnInit() {
    // Create your form here

    this.subscription = this.capValues.valueChanges.subscribe(data => {
        this.total = data.reduce((a,b) => a + +b.fdnTotalShares, 0)
    });
}

get capValues() {
    return this.form.get('cap_values') as FormArray;
}

Now wherever you want to display the total in your template just use {{total}} and it will dynamically update as you change values in the fdnTotalShares input.

Lastly, do not forget to unsubscribe from valueChanges. This is why I have introduced the subscription variable as seen in the code snippet above.

ngOnDestroy() {
    this.subscription.unsubscribe();
}

Here is a simple working example on StackBlitz.

Upvotes: 1

Chanaka Weerasinghe
Chanaka Weerasinghe

Reputation: 5742

Here I have Tried . One

 console.log(this.form.length);
 console.log(this.form.value);

Upvotes: 0

Poldo
Poldo

Reputation: 1932

You can loop through your form controls

let total = 0;
form.controls.foreach(data => {
  total += data.fdnTotalShares.value;
})

To make sure proper form control is being get use console log

Upvotes: 0

Related Questions