AngularJS发票计算问题:总计不显示+折扣VAT下拉改输入框
发票计算功能修复与改造方案
核心问题梳理
- 总计金额无法显示:HTML中总计行的
<strong>标签未绑定{{Sale.TotalAmount}},且错误地将插值表达式写在td的value属性(该属性不适用于表格单元格)。 - 交互需求改造:需要将折扣、VAT的下拉选择框替换为手动输入文本框,实现值变更时自动联动计算所有金额。
改造后代码实现
1. HTML部分修改
将折扣、VAT的下拉框改为数字输入框,绑定ng-change事件触发计算,同时修复总计显示:
<div class="row"> <div class="col-lg-4 col-sm-5"> </div> <div class="col-lg-4 col-sm-5 ml-auto"> <table class="table table-clear"> <tbody> <tr> <td class="left"> <strong>Subtotal</strong> </td> <td class="right">${{Sale.Subtotal || 0}}</td> </tr> <tr> <td class="left"> <strong> Discount % <!-- 替换下拉框为数字输入框,绑定ng-change触发计算 --> <input type="number" ng-model="Sale.DiscountParcentage" ng-change="CalculateDiscount();CalculateVat();" min="0" max="100" placeholder="输入折扣百分比"> </strong> </td> <td class="right">${{Sale.DiscountAmount || 0}}</td> </tr> <tr> <td class="left"> <strong> VAT % <!-- 替换下拉框为数字输入框,绑定ng-change触发计算 --> <input type="number" ng-model="Sale.VatParcentage" ng-change="CalculateVat();" min="0" max="100" placeholder="输入VAT百分比"> </strong> </td> <td class="right">${{Sale.VatAmount || 0}}</td> </tr> <tr> <td class="left"> <strong>Total</strong> </td> <!-- 修复总计显示,绑定插值表达式到strong标签 --> <td class="right"> <strong>${{Sale.TotalAmount || 0}}</strong> </td> </tr> </tbody> </table> </div> </div>
2. JS逻辑优化
确保数值联动计算,处理空值/非数字情况,避免出现NaN:
$scope.AddNewRow = function () { $scope.InvoiceCart.push({ ProductId: null, CategoryName: '', UnitPrice: 0, Quantity: 1, LineTotal: 0 }); } $scope.SetValueOfProduct = function (productId) { var dataObj = $filter('filter')($scope.ProductList, { ProductId: parseInt(productId) })[0]; const index = $scope.InvoiceCart.findIndex((x) => x.ProductId === productId); if (dataObj) { $scope.InvoiceCart[index].CategoryName = dataObj.CategoryName; $scope.InvoiceCart[index].UnitPrice = dataObj.SalesPrice; $scope.InvoiceCart[index].LineTotal = $scope.InvoiceCart[index].UnitPrice * $scope.InvoiceCart[index].Quantity; // 选择商品后自动计算小计、折扣、VAT和总计 $scope.SubTotalCalculation(); $scope.CalculateDiscount(); $scope.CalculateVat(); } } $scope.OnChangeLineTotalSet = function (productId) { const index = $scope.InvoiceCart.findIndex((x) => x.ProductId === productId); $scope.InvoiceCart[index].LineTotal = $scope.InvoiceCart[index].UnitPrice * $scope.InvoiceCart[index].Quantity; // 修改数量/单价后自动联动计算所有金额 $scope.SubTotalCalculation(); $scope.CalculateDiscount(); $scope.CalculateVat(); } $scope.SubTotalCalculation = function () { $scope.Sale.Subtotal = 0; for (var i = 0; i < $scope.InvoiceCart.length; i++) { $scope.Sale.Subtotal += $scope.InvoiceCart[i].LineTotal || 0; } } $scope.CalculateDiscount = function () { // 处理空值,默认0 const discountPercent = $scope.Sale.DiscountParcentage || 0; $scope.Sale.DiscountAmount = ($scope.Sale.Subtotal * discountPercent) / 100; } $scope.CalculateVat = function () { // 处理空值,默认0 const vatPercent = $scope.Sale.VatParcentage || 0; const afterDiscount = $scope.Sale.Subtotal - ($scope.Sale.DiscountAmount || 0); $scope.Sale.VatAmount = (afterDiscount * vatPercent) / 100; $scope.Sale.TotalAmount = afterDiscount + $scope.Sale.VatAmount; } $scope.RowDelete = function (index) { if (index > -1) { $scope.InvoiceCart.splice(index, 1); } // 删除行后自动计算所有金额 $scope.SubTotalCalculation(); $scope.CalculateDiscount(); $scope.CalculateVat(); } $scope.SaveInvoice = function () { $scope.Sale.OrderNo = $("#OrderNo").val(); var data = JSON.stringify({ sale: $scope.Sale, salesDetails: $scope.InvoiceCart }); return $.ajax({ contentType: 'application/json; charset=utf-8', dataType: 'json', type: 'POST', url: "/Home/SaveInvoiceSale", data: data, success: function (result) { alert(result.IsSuccess ? "Save Success!" : "Save failed!"); }, error: function () { alert("Error!") } }); }
关键改动说明
- 输入框替换:将折扣、VAT的下拉框改为
type="number"的输入框,添加min/max限制范围,绑定ng-change事件触发计算。 - 总计显示修复:将总计金额的插值表达式移到
<strong>标签内,同时添加|| 0处理空值,避免显示空白。 - 联动计算优化:在商品选择、数量/单价修改、行删除等操作后,自动触发完整的计算流程(小计→折扣→VAT→总计),保证所有数值实时同步。
- 空值处理:在计算逻辑中添加
|| 0,避免因未输入值导致NaN的出现。
内容的提问来源于stack exchange,提问作者Salman Amjad
相关产品推荐
相关产品推荐

