3

我有我的反应形式,看起来像这样

<form [formGroup]="addInvoiceForm" (submit)="onAddInvoiceFormSubmit()">
  <div [formArrayName]="itemRows">
    <div *ngFor="let itemrow of addInvoiceForm.controls.itemRows.controls; let i=index" [formGroupName]="i">
      <input autocomplete="off" type="text" formControlName="itemqty">
      <input autocomplete="off" type="text" formControlName="itemrate">

      <!-- the input field below is to be summed -->
      <input autocomplete="off" type="text" formControlName="itemamt" [ngModel]="itemrow.get('itemqty').value * itemrow.get('itemrate').value">

    </div>
  </div>
  <button type="button" (click)="addItemRow()">Add New Row</button>
</form>

我想对用户创建的所有行的 itemamt 求和并将它们传递到表单数据中。有人可以帮助我,告诉我如何汇总表单中的所有 itemamt 字段并并排显示用户的总金额是多少?

4

4 回答 4

7

我确实想知道是否有更好的方法,但我尝试使用吸气剂,它抱怨Expression has changed...尝试添加ChangeDetectorRef到混合物中导致无限循环。

所以我决定在表单数组中监听valueChanges,我也需要使用ChangeDetectorRef,所以首先导入它并将其注入你的构造函数:

import { ChangeDetectorRef } from '@angular/core';

constructor(private fb: FormBuilder, private ref: ChangeDetectorRef) { }

然后valueChanges

// subscribe to changes in the formArray
this.invoiceForm.get('itemRows').valueChanges.subscribe(values => {
  // reset the total amount  
  this.summed = 0;
  const ctrl = <FormArray>this.invoiceForm.controls['itemRows'];
    // iterate each object in the form array
    ctrl.controls.forEach(x => {
      // get the itemmt value and need to parse the input to number
      let parsed = parseInt(x.get('itemamt').value)
      // add to total
      this.summed += parsed
      this.ref.detectChanges()
    });
  }) 

为了构建表单,您需要添加一个新的表单控件,因为您希望它成为表单的一部分:

this.invoiceForm = this.fb.group({
  itemRows: this.fb.array([this.initItemRows()])
  summed: [null] // here
}); 

在您的模板中:

<input readonly [ngModel]="summed" formControlName="summed" />

演示


编辑:

我建议你使用我们的好yurzui建议的解决方案,比我的解决方案优雅得多,所以内部valueChanges使用reduce()

resolvedPromise.then(() => {
  this.summed = values.reduce((acc, cur) => acc + cur.itemamt, 0);
});

和变量:

const resolvedPromise = Promise.resolve(null);
于 2017-05-10T18:16:51.977 回答
0

如果您想在提交发布请求之前对所有值求和,您可以这样做。

在您的提交请求中传递表单值

<form [formGroup]="addInvoiceForm" novalidate (submit)="onAddInvoiceFormSubmit(addInvoiceForm.value)">

</form>

在组件文件中。

您将更新表单对象。只需迭代 addInvoiceForm.itemRows 并创建总和。

onAddInvoiceFormSubmit(addInvoiceForm){
// you will have update form object. just iterate the addInvoiceForm.itemRows and create sum.

}

注意:-在启用提交按钮之前进行所有验证

于 2017-05-10T15:30:00.943 回答
0

求和逻辑最好在组件类中,而不是在 HTML 中。您可以使用返回总和的 getter 定义一个属性。

一般来说,语法是这样的:

get sum():number {
    let summed = 0;
    for (var key in sample) {
        summed += sample[key];
    };
    return summed; 
} 

注意:您也可以使用 Array.prototype.reduce(),但上面的语法更简单。

另外,请考虑使用 ngSubmit 而不是提交。

于 2017-05-10T15:15:25.270 回答
0

yurzui建议的回答

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';

const resolvedPromise = Promise.resolve(null);

@Component({
  selector: 'my-app',
  template: ...
})


export class App implements OnInit {
    public invoiceForm: FormGroup;
    summed: number;

    constructor(private fb: FormBuilder, private ref: ChangeDetectorRef) {}
    
    ngOnInit(){
        this.invoiceForm = this.fb.group({
          itemRows: this.fb.array([this.initItemRows(), this.initItemRows()])
        });
        
        this.invoiceForm.get('itemRows').valueChanges.subscribe(values => {
          resolvedPromise.then(() => {
            this.summed = values.reduce((acc, cur) => acc + cur.itemamt, 0);
          });
        })
    }
}
于 2020-07-17T09:04:48.750 回答