反应式表单中基于复选框的计算

Calculation Based on Checkbox in Reactive Forms

我对如何获取复选框值感到困惑,所以我得到了 "amount" 和 "total" 值。计算非常简单。复选框值为 1.20 或 20%。金额为(数量*价格)/复选框值,如果复选框值有勾选就可以了。而总价值仅为(数量*价格)。这是我的代码的 link。

更新!!!现在可以使用了,但问题是它不会自动计算,但我必须在输入字段外单击才能更新它。

COMPLETE CODE IS HERE

 onChange(isChecked, id){
    console.log(isChecked)
    let quantity = (<FormArray>this.myForm.controls['rows']).controls[id]['controls']['quantity'].value
    let price = (<FormArray>this.myForm.controls['rows']).controls[id]['controls']['price'].value
    let checkbox = (<FormArray>this.myForm.controls['rows']).controls[id]['controls']['checkbox'].value

    let x = (<FormArray>this.myForm.controls['rows']).at(id);
    if(isChecked){
      x.patchValue({
        amount: (quantity * price)/checkbox,
        total: quantity * price
    });
    }

    else {
      x.patchValue({
        amount: (quantity * price)/checkbox,
        total: (quantity * price)/checkbox,
    });
    }
  }

Josep,我们在使用ReactiveForm的时候,通常会控制订阅AbstractControl.valuesChange的变化。

因此您的表单不需要 (cange) 或 (NgModel),只需

<form class="form-horizontal" [formGroup]="myForm" (ngSubmit)="onCreateProduct()" >
  <div class="card">
    <div class="card-block" formArrayName="rows">
      <table class="table">
   ...
        </thead>
        <tbody>
          <tr *ngFor="let row of myForm.controls.rows.controls; let i = index" [formGroupName]="i">
            <td>{{row.value.material_id}}</td>
            <td>{{row.value.material_name}}</td>
            <td><input class="col-md-6" type ="number" formControlName="quantity" ></td>
            <td><input class="col-md-6" type ="number" formControlName="price" ></td>
            <td><input type="checkbox" class="col-md-6" formControlName="dis_checkbox" > 20 %</td>
            <td><input class="col-md-6" formControlName="amount" readonly disabled ></td>
             <td><input class="col-md-6" formControlName="total" readonly disabled></td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</form>

然后我们控制"changes"在你的代码中加入,在pathValues

之后
  patchValues() {
    let rows = this.myForm.get('rows') as FormArray;
    this.orders.forEach(material => {
...
    })
    setOnChange() //<--call a function
}
setOnChange()
{
    const formarray=this.myForm.get('rows') as FormArray;
    for (let i=0;i<rows.length;i++)
    { 
      formarray.at(i).valueChanges.subscribe(val=>{
      //see that in val we have all the values
      //val.quantity,val.price,val.dis_checkbox...

      //I use an auxiliar variables to get the controls "total" and "amount"
      let controlTotal=(this.myForm.get('rows') as FormArray).at(i).get('total')
      let controlAmount=(this.myForm.get('rows') as FormArray).at(i).get('amount')     

      let value=(val.quantity)*(val.price);

      if (controlTotal.value!=value)  //Only when the values are not equal
        controlTotal.setValue(value);

      value=val.dis_checkbox?value/val.checkbox:value;
      if (controlAmount.value!=value)  //Only when the values are not equal
        controlAmount.setValue(value); 
    });
    }
  }

当我们使用 valueChanges 时,我们可以订阅一个 uniq 控件、formArray (mychoice) 的一行或所有表单。 好的,代码还不完整。通常情况下,如果我们有 "calculated field"(在本例中为 "total" 和 "amount"),我们不需要让这些字段属于表单。为什么不使用对象数组 (e.g.totals=[{total:0,ammount:0}{total:0,ammount:0}..] 和 change/display 值?

<tr *ngFor="let row of myForm.controls.rows.controls; let i = index" [formGroupName]="i">
             ...
            <td><input class="col-md-6" type ="number" formControlName="quantity" ></td>
            <td><input class="col-md-6" type ="number" formControlName="price" ></td>
            <td><input type="checkbox" class="col-md-6" formControlName="dis_checkbox" > 20 %</td>
  <!--see that don't belong to the form, I use the variable "totals"-->
            <td><input class="col-md-6" [value]="totals[i].amount" readonly disabled ></td>
             <td><input class="col-md-6" [value]="totals[i].amount" readonly disabled></td>
          </tr>

抱歉耽搁了。我想使用 "auxiliar variable" "totals" 你必须

//declare the variable at first
totals:any[]=[] //totals will be like, e.g. [{total:0,amount:0},{total:10,amount:23}...]

//In patchValues
    this.orders.forEach(material => {
      material.materials.forEach(x => {
        rows.push(this.fb.group({
          material_id: x.id,
          material_name: x.name,
          quantity: [null, Validators.required],
          price: [null, Validators.required],
          dis_checkbox: [true],
          checkbox: [1.20]
        })) //see that total and amount is NOT in the form
        this.totals.push({amount:0,total:0});  //<--add this line
      })
    })

//And finally, we change the "setOnchange" (I commented the lines that you don't need)
setOnChange()
{
    const formarray=this.myForm.get('rows') as FormArray;
    for (let i=0;i<formarray.length;i++)
    { 
      formarray.at(i).valueChanges.subscribe(val=>{

      //"total" and "amount" are simply variables
      //we needn't look for the controls (not exist)
//      let controlTotal=(this.myForm.get('rows') as FormArray).at(i).get('total')
//      let controlAmount=(this.myForm.get('rows') as FormArray).at(i).get('amount')     

      let value=(val.quantity)*(val.price);
      this.totals[i].total=value;  //<--just update the value of the variable
//      if (controlTotal.value!=value)  
//        controlTotal.setValue(value);

      value=val.dis_checkbox?value/val.checkbox:value;
      this.totals[i].amount=value;  //<--idem
//      if (controlAmount.value!=value)  
//        controlAmount.setValue(value); 
    });
    }
  }