AngularJS中ng-change切换选项后新增行复用旧值问题求助
问题根源分析
我一眼就看出问题出在哪了——你现在所有行的表单控件都绑定了同一个全局的payment_data对象,下拉框的ng-model也没和当前行的条目关联起来!这样一来,新增行时会直接继承全局变量的旧值,甚至切换任意一行的下拉框,所有行的输入框都会同步变化,完全达不到每行独立的效果。
修复方案
我们需要把每一行的下拉框和输入框都绑定到form.payments数组里的当前行对象上,让各行数据彻底独立。具体修改如下:
1. 调整HTML控件的绑定(核心修改)
假设你的表格行是在ng-repeat="payment in form.payments"循环中,修改每个控件的ng-model:
<!-- 下拉框:绑定到当前行的payment.invoice,避免全局共享 --> <td class="minwd100"> <select class="form-control" id="invoice_id_{{$index}}" name="invoice_id_{{$index}}" ng-options="invoice as invoice.invoice_number+ ' - '+invoice.client_name+' - '+invoice.invoice_converted_total for invoice in approved_invoices track by invoice.invoice_id" ng-model="payment.invoice" ng-change="changeInvoice(payment)"> </select> </td> <!-- 付款金额:绑定到当前payment的独立属性 --> <td class="minwd100"> <input type="text" class="form-control" id="payment_amount_{{$index}}" ng-model="payment.payment_amount" name="payment_amount_{{$index}}" placeholder="Enter {{form_data.payment_amount.label}}" ng-focus="form_data.payment_amount.error = ''" /> </td> <!-- 汇率:绑定到当前payment的独立属性 --> <td class="minwd100"> <input type="text" class="form-control" id="payment_conversion_{{$index}}" ng-model="payment.payment_conversion_rate" name="payment_conversion_{{$index}}" placeholder="Enter {{form_data.payment_conversion_rate.label}}" ng-focus="form_data.payment_conversion_rate.error = ''" /> </td> <!-- 转换后金额:绑定到当前payment的独立属性 --> <td class="minwd100"> <input type="text" class="form-control" id="payment_converted_amount_{{$index}}" ng-model="payment.payment_converted_amount" name="payment_converted_amount_{{$index}}" placeholder="Enter {{form_data.payment_converted_amount.label}}" ng-focus="form_data.payment_converted_amount.error = ''" ng-readonly="true"/> </td> <td class="wd80"> <div class="dt-options"> <a href ng-if="$index === form.payments.length - 1" ng-click="addContact()" title="Add Contact"><i class="fa fa-plus fa-lg"></i></a> <a href ng-if="form.payments.length > 1" ng-click="removeContact($index)" title="Remove Contact"><i class="fa fa-trash-o fa-lg"></i></a> </div> </td>
小贴士:给每个控件的
id和name加上_{{$index}},确保每行的控件ID唯一,避免DOM冲突。
2. 更新JS函数逻辑
修改changeInvoice和addContact,让它们操作当前行的独立对象:
// 传入当前行的payment对象,只更新该行的属性 $scope.changeInvoice = function (payment){ if (!payment.invoice) return; // 处理未选中选项的边界情况 payment.payment_amount = payment.invoice.invoice_converted_total; payment.payment_conversion_rate = payment.invoice.invoice_conversion_rate; payment.payment_converted_amount = payment.invoice.invoice_converted_balance; $scope.client_id = payment.invoice.client_id; payment.invoice_id = payment.invoice.invoice_id; // 把选中的发票ID存到当前行对象中 }; // 新增行时初始化独立的空结构,避免继承旧值 $scope.addContact = function() { $scope.form.payments.push({ invoice_id: '', invoice: null, // 预留选中发票对象的位置 payment_amount: '', payment_conversion_rate: '', payment_converted_amount: '' }); }; $scope.removeContact = function(index) { $scope.form.payments.splice(index, 1); };
3. 修复原理说明
- 每一行的控件都绑定到
form.payments数组中对应的单个对象,各行数据完全独立,不会互相干扰。 - 切换下拉框时,
changeInvoice只更新当前行的属性,其他行不受影响。 - 新增行时初始化了全新的空对象,不会再继承全局变量的旧值。
额外优化建议
如果觉得ng-options里的显示文本太冗长,可以提取一个过滤器简化HTML:
// 定义一个自定义过滤器 app.filter('invoiceDisplay', function() { return function(invoice) { return `${invoice.invoice_number} - ${invoice.client_name} - ${invoice.invoice_converted_total}`; }; });
然后在HTML中使用:
ng-options="invoice as (invoice | invoiceDisplay) for invoice in approved_invoices track by invoice.invoice_id"
内容的提问来源于stack exchange,提问作者Namrata Rathod
相关产品推荐
相关产品推荐

