1

In Invoice Form I am having the dropdown with the products names I want to calculate the Sub Total of the selected product name depending on the quantity and price entered by the user.

I am implementing through formArray Form control values how to display in the template?

I tried but unable to get the desired the result.

ngOnInit() {
    this.j = 0;
    this.invoiceForm = this.fb.group({
        invoiceItems: this.fb.array([this.ItemsRows()])
    });

}

ItemsRows() {
    return this.fb.group({
        invoiceSelect: new FormControl(''),
        qty: new FormControl(''),
        price: new FormControl('')

    })
}

get invoiceItems() {
    return this.invoiceForm.controls.invoiceItems as FormArray;
}

addItems() {
    this.invoiceItems.push(this.fb.group(this.ItemsRows()))
}

onChange(event) {
    this.j = event;
}
<form [formGroup]="invoiceForm">
  <div formArrayName="invoiceItems" class="uk-grid-small" uk-grid>
    <ng-container *ngFor="let item of invoiceForm.get('invoiceItems').controls; let i=index"
    [formGroupName]="i">
    <table class="uk-table uk-table-justify uk-table-divider">
      <thead>
        <tr>
          <th class="uk-width-small">Product Name</th>
          <th>Quantity</th>
          <th>Price</th>
          <th>Total</th>
          <th><button class="uk-button-danger" (click)="addItems()">+</button></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>
            <div class="uk-width-1-2@m">
              <select (change)="onChange($event.target.value)" name="invoiceSelect"
                formControlName="invoiceSelect" class="uk-select uk-margin-top ">
              <option *ngFor="let productDetail of product; let productIndex=index"
              [value]="productIndex">
              {{ productDetail.productName }} </option>
              </select>
            </div>
          </td>
          <td>
            <div class="uk-width-1-2@m">
              <input class="uk-input uk-margin-top uk-margin-right" type="number" name="quantity"
                formControlName="qty" min="1" max="10" />
            </div>
          </td>
          <td>
            <div>
              <input class="uk-input uk-margin-right uk-margin-top" id="price" name="price"
              formControlName="price" type="number"
              [(ngModel)]="product.length === 0 ? tempPrice: product[j]['price']" />
            </div>
          </td>
          <td>
            <div>
              <p>
                {{ item.value.qty * item.value.price | currency }}
              </p>
            </div>
          </td>
        </tr>
        <tr>
          <td><input name="item.discount" size="10" value="0"></td>
          <td>Discount: {{(1-item.discount/100) * (item.value.qty * item.value.price)|currency}}</td>
        </tr>
      </tbody>
    </table>
    </ng-container>
  </div>
</form>

To display the Sub Total of all the selected products.

2
  • I'd be interested if there is a better way but I've previously done a similar thing using RxJS and subscribing to valueChanges codereview.stackexchange.com/questions/222712/… Commented Jul 8, 2019 at 19:25
  • Change your addItems function to addItems() { this.invoiceItems.push(this.ItemsRows()); } since itemsRows() already returns a formGroup. Also avoid using ngModel and formControl together. Commented Jul 8, 2019 at 19:44

1 Answer 1

2

I would do this

define a variable called subTotal

subTotal: number;

in ngOnInit after setup form

this.invoiceForm.valueChanges().subscribe(value => {
   this.subTotal = value.invoiceItems.reduce((sum, item) => sum += (item.qty || 0) * (item.price || 0) ,0)
})

and in your html

{{ subTotal | currency }}

p.s Don't forget to unsubscribe from form.valueChanges

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.