You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular表单数组中根据产品与数量自动计算并显示价格

Angular产品账单页面自动计算价格功能实现

我正在使用Angular开发产品账单页面,需求是:当选择产品(例如“apple”)和数量后,自动计算价格(计算公式:价格=产品单价×数量,示例:10×1=10)并显示在对应的price输入框中。

当前组件HTML代码

<form [formGroup]="productFormarray" (ngSubmit)="onSubmit()">
  <div class="reg-right">
    <div class="formGroup">
      <label for="customername" class="form-label">Customer Name</label>
      <input type="text" class="form-control" id="customername" placeholder="Customer Name"
        formControlName="customername">
    </div>
    <div class="formGroup" formArrayName="productdetails">
      <div class="table-responsive">
        <table class="table table-bordered">
          <thead>
            <tr>
              <td style="width:50%">
                Product Name
              </td>
              <td style="width:15%">
                Quantity
              </td>
              <td style="width:20%">
                Price
              </td>
            </tr>
          </thead>
          <tr *ngFor="let product of productdetailsarray.controls; let i=index" [formGroupName]="i">
            <td style="width:50%">
              <div class="formGroup">
                <select class="form-control" id="productname" formControlName="productname" name="productname" placeholder="Product Name">
                  <option disabled>select product</option>
                  <option *ngFor="let product of productlist" [ngValue]="product.productname">
                    {{product.productname}}
                  </option>
                </select>
              </div>
            </td>
            <td style="width:15%">
              <div class="formGroup">
                <select class="form-control" id="quantit" formControlName="quantit" name="quantit">
                  <option *ngFor="let quantity of quantitylist" [ngValue]="quantity">
                    {{quantity}}
                  </option>
                </select>
              </div>
            </td>
            <td style="width:20%">
              <div class="formGroup">
                <input type="text" class="form-control" id="price" formControlName="price" placeholder="Price "
                  name="price" [value]="'33'">
              </div>
            </td>
            <td>
              <a type="button" class="btn btn-primary btn-sm mt-4" style="background-color: red;"
                (click)="removeProduct(i)">Remove (-)</a>
            </td>
          </tr>
        </table>
      </div>
      <a type="button" class="btn btn-secondary" style="background-color: green;"
        (click)="addNewProduct()">Add(+)</a>
      <br/>
    </div>
    <div class="mb-4 mt-4 col-md-12">
      <div class="formGroup">
        <label class="form-check-label">
          <input class="form-check-input" formControlName="remember" type="checkbox" name="remember"> Remember
          me
        </label>
      </div>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </div>
</form>

当前组件TypeScript代码

import { Component, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormControl, FormArray, FormBuilder, NgForm, Validators } from '@angular/forms'
import { Observable, of } from 'rxjs';
import { toArray } from 'rxjs';

@Component({
  selector: 'app-billing',
  templateUrl: './billing.component.html',
  styleUrls: ['./billing.component.css']
})
export class BillingComponent implements OnInit {

  name = 'Bill';
  productsForm!: NgForm;
  @ViewChild('productsForm') productsForminput!: NgForm;

  productFormarray: any;
  quantitylist = [0.5, 1, 1.5];
  items!: FormArray;
  ind: number = 0;
  i: number = 0;
  productlist = [{ productname: "apple", price: 10 }, { productname: "orange", price: 10 }, { productname: "lemon", price: 30 }];

  constructor(private fb: FormBuilder) {
    this.productFormarray = new FormGroup({
      customername: new FormControl('', Validators.required),
      productdetails: new FormArray([]),
      remember: new FormControl('true')
    })
  }

  addNewProduct() {
    this.items = this.productFormarray.get('productdetails') as FormArray;
    this.items.push(this.createNewProduct());
    this.productFormarray.get('productdetails').controls[this.ind].get('quantit').setValue(this.quantitylist[1]);
    this.ind = this.ind + 1;
  }

  createNewProduct(): FormGroup {
    return new FormGroup({
      productname: new FormControl('', Validators.required),
      quantit: new FormControl('1', Validators.required),
      price: new FormControl('', Validators.required)
    })
  }

  removeProduct(index: any) {
    this.items = this.productFormarray.get('productdetails') as FormArray;
    this.items.removeAt(index);
  }
  get productdetailsarray() {
    return this.productFormarray.get('productdetails') as FormArray;
  }

  ngOnInit() {
    this.addNewProduct();
  }

  onSubmit() {
  }
}

实现方案

1. 修改HTML模板

给产品和数量下拉框添加(change)事件触发价格计算,同时移除price输入框的硬编码值并设置为只读:

<tr *ngFor="let product of productdetailsarray.controls; let i=index" [formGroupName]="i">
  <td style="width:50%">
    <div class="formGroup">
      <select class="form-control" id="productname" formControlName="productname" name="productname" placeholder="Product Name"
        (change)="calculatePrice(i)">
        <option disabled>select product</option>
        <option *ngFor="let product of productlist" [ngValue]="product.productname">
          {{product.productname}}
        </option>
      </select>
    </div>
  </td>
  <td style="width:15%">
    <div class="formGroup">
      <select class="form-control" id="quantit" formControlName="quantit" name="quantit"
        (change)="calculatePrice(i)">
        <option *ngFor="let quantity of quantitylist" [ngValue]="quantity">
          {{quantity}}
        </option>
      </select>
    </div>
  </td>
  <td style="width:20%">
    <div class="formGroup">
      <input type="text" class="form-control" id="price" formControlName="price" placeholder="Price "
        name="price" readonly>
    </div>
  </td>
  <td>
    <a type="button" class="btn btn-primary btn-sm mt-4" style="background-color: red;"
      (click)="removeProduct(i)">Remove (-)</a>
  </td>
</tr>

2. 修改TypeScript组件代码

添加价格计算方法,并优化表单初始化逻辑:

import { Component, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormControl, FormArray, FormBuilder, NgForm, Validators } from '@angular/forms'

@Component({
  selector: 'app-billing',
  templateUrl: './billing.component.html',
  styleUrls: ['./billing.component.css']
})
export class BillingComponent implements OnInit {

  name = 'Bill';
  productsForm!: NgForm;
  @ViewChild('productsForm') productsForminput!: NgForm;

  productFormarray: any;
  quantitylist = [0.5, 1, 1.5];
  items!: FormArray;
  ind: number = 0;
  productlist = [{ productname: "apple", price: 10 }, { productname: "orange", price: 10 }, { productname: "lemon", price: 30 }];

  constructor(private fb: FormBuilder) {
    this.productFormarray = new FormGroup({
      customername: new FormControl('', Validators.required),
      productdetails: new FormArray([]),
      remember: new FormControl('true')
    })
  }

  addNewProduct() {
    this.items = this.productFormarray.get('productdetails') as FormArray;
    this.items.push(this.createNewProduct());
    const newProduct = this.productdetailsarray.controls[this.ind] as FormGroup;
    newProduct.get('quantit')?.setValue(this.quantitylist[1]);
    this.ind++;
  }

  createNewProduct(): FormGroup {
    return new FormGroup({
      productname: new FormControl('', Validators.required),
      quantit: new FormControl('1', Validators.required),
      price: new FormControl('', Validators.required)
    })
  }

  removeProduct(index: any) {
    this.items = this.productFormarray.get('productdetails') as FormArray;
    this.items.removeAt(index);
  }

  get productdetailsarray() {
    return this.productFormarray.get('productdetails') as FormArray;
  }

  // 计算并更新当前行价格
  calculatePrice(index: number) {
    const productGroup = this.productdetailsarray.controls[index] as FormGroup;
    const productName = productGroup.get('productname')?.value;
    const quantity = productGroup.get('quantit')?.value;

    if (productName && quantity) {
      const selectedProduct = this.productlist.find(item => item.productname === productName);
      if (selectedProduct) {
        const totalPrice = selectedProduct.price * quantity;
        productGroup.get('price')?.setValue(totalPrice);
      }
    } else {
      productGroup.get('price')?.setValue('');
    }
  }

  ngOnInit() {
    this.addNewProduct();
  }

  onSubmit() {
    // 提交时可获取完整表单数据
    console.log(this.productFormarray.value);
  }
}

核心说明

  • 通过(change)事件监听产品和数量的选择变化,触发价格计算
  • 在calculatePrice方法中,根据当前行索引获取表单控件,匹配产品单价后计算总价并更新price输入框
  • 将price输入框设置为readonly,避免用户手动修改计算结果
  • 优化了addNewProduct中的控件获取逻辑,提升代码可读性

内容的提问来源于stack exchange,提问作者Reegan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:27:31