【问题标题】:How to update value of one formControl based on the changes made in other formControl values?如何根据对其他 formControl 值所做的更改来更新一个 formControl 的值?
【发布时间】:2021-11-11 04:05:58
【问题描述】:

我用三个可编辑的 formControls 制作了一个有角度的反应形式。 HTML 代码:

  <table class="table-details">
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Carbohydrates</th>
      <th>Fats</th>
      <th>Protein</th>
      <th>Calories</th>
      <th style="padding-left: 4rem">Status</th>
      <th>Action</th>
    </tr>
    <tr *ngFor="let food of foods; index as index">
      <td>{{ food.id }}</td>
      <td>
        <editable class="name" (update)="updateField(index, 'name')">
          <ng-template appViewMode>
            {{food.name}}
            <mat-icon>edit</mat-icon>
          </ng-template>
          <ng-template appEditMode>
            <input [formControl]="getControl(index, 'name')" focusable>
          </ng-template>
        </editable>
      </td>
      <td>
        <editable class="carbohydrates" (update)="updateField(index, 'carbohydrates')">
          <ng-template appViewMode>
            {{food.carbohydrates}} gms
            <mat-icon>edit</mat-icon>
          </ng-template>
          <ng-template appEditMode>
            <input [formControl]="getControl(index, 'carbohydrates')" focusable>
          </ng-template>
        </editable>
      </td>
      <td>
        <editable class="fats" (update)="updateField(index, 'fats')">
          <ng-template appViewMode>
            {{food.fats}} gms
            <mat-icon>edit</mat-icon>
          </ng-template>
          <ng-template appEditMode>
            <input [formControl]="getControl(index, 'fats')" focusable>
          </ng-template>
        </editable>
      </td>
      <td>
        <editable class="protein" (update)="updateField(index, 'protein')">
          <ng-template appViewMode>
            {{food.protein}}gms
            <mat-icon>edit</mat-icon>
          </ng-template>
          <ng-template appEditMode>
            <input [formControl]="getControl(index, 'protein')" focusable>
          </ng-template>
        </editable>
      </td>
      <td>
        <div>
          <p [formControl]="getCalories()">
            {{food.calories}} kcals
          </p>
        </div>
      </td>
      <td>
        <div class="boolean">
          <mat-icon>lens</mat-icon>
          Active
        </div>
      </td>
      <td>
        <div class="actions">
          <mat-icon>delete</mat-icon>
        </div>
      </td>
    </tr>
  </table>

这是ts代码:

export class FoodDetailsComponent implements OnInit {

  items!: FormArray

  foods:any = FOODDATAS;

  constructor(private fb : FormBuilder) {}

  ngOnInit(): void {
    const toGroup = this.foods.map((food:any) => {
      return new FormGroup({
        name: new FormControl(food.name,[
          Validators.required,
          Validators.pattern(/^[a-zA-Z]*$/)
        ]),
        carbohydrates: new FormControl(food.carbohydrates, [
          Validators.required,
          Validators.pattern(/^\d+(\.\d{1,2})?$/)
        ]),
        fats: new FormControl(food.fats, [
          Validators.required,
          Validators.pattern(/^\d+(\.\d{1,2})?$/)
        ]),
        protein: new FormControl(food.protein, [
          Validators.required,
          Validators.pattern(/^\d+(\.\d{1,2})?$/)
        ]),
        calories: new FormControl(food.calories, [
          Validators.required
        ])
      });
    });
    this.items = new FormArray(toGroup)

  }

  getCalories() : FormControl {
    const carbs:any = this.items.get('carbohydrates.2.inArray')
    const protein:any = this.items.get('protein.3.inArray')
    const fats:any = this.items.get('fats.2.inArray')
    return ((carbs * 4) + (protein * 4) + (fats * 9)) as unknown as FormControl
  }

  getControl(index: number, field: string): FormControl {
    return this.items.at(index).get(field) as FormControl;
  }

  updateField(index: number, field: string) {
    const control = this.getControl(index, field);
    if (control.valid) {
      this.foods = this.foods.map((e: any, i: number) => {
        if (index === i) {
          return {
            ...e,
            [field]: control.value
          };
        }
        return e;
      });
    }
  }

“卡路里”的值,我想根据“碳水化合物”、“蛋白质”和“脂肪”的值自动计算,使用这个逻辑

function getCalories(carbs:Double, protein:Double, fat:Double) {
   return carbs x 4 + protein x 4 + fats x 9
}

我希望它监控其他三个 formControl 值的变化。我尝试使用valueChanges,但它不适用于 fromArray。(PS-如何访问 fromArray 的值?)

提前致谢

【问题讨论】:

    标签: angular typescript angular-reactive-forms angular-forms angular-validation


    【解决方案1】:

    ValueChanges 不起作用,因为您没有使用父表单组指令包装表单数组指令。另外我建议不要使用这么多模板函数,这是一种更简单的访问控件的方法,让 formarray 为您处理它,示例如下

    <!-- below is what you are missing, a parent form group-->
    <table [formGroup]="formGroup">
      <tbody formArrayName="items">
          <tr 
          *ngFor="let item of formGroup.get('items').controls; let i = index;"> 
              <td [formGroupName]="i">
              <input formControlName="carbohydrates" placeholder="Item name">
              </td>
          </tr>
       </tbody>
    </table>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-25
      • 2020-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-13
      • 2017-01-12
      相关资源
      最近更新 更多