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
相关产品推荐
相关产品推荐

