AngularJS ng-repeat动态表单验证异常问题求助
解决AngularJS ng-repeat动态表单独立验证问题
嘿,刚接触AngularJS遇到这种动态表单验证的问题很正常,我帮你梳理下问题所在,再给你完整的解决方案!
先说说你代码里的核心问题
- ng-model语法错误:你写的
myModel.['contbanca' + $index]多了个多余的点,而且用零散变量存多个账户信息太容易混乱,更推荐用数组结构管理。 - 重复的name和共用ng-model:所有重复项里的下拉框都用了
name="banca",还绑定到同一个myModel.banca,这直接导致所有下拉框共享验证状态,自然会同步变化。 - 表单控件引用方式不对:
userFieldForm.['contbanca' + $index]这种写法在AngularJS里会失效,应该去掉点,写成userFieldForm['contbanca' + $index]。 - 删除逻辑不精准:现在点击任何"X"都删最后一项,而不是当前点击的项,需要传递
$index来指定删除位置。
完整解决方案
第一步:重构模型结构
把零散的变量改成数组,每个账户作为数组里的独立对象,方便管理和绑定:
app.controller('ValidationCtrl', ["$scope", "$state", "$timeout", "SweetAlert", function ($scope, $state, $timeout, SweetAlert) { // 初始化账户列表和对应模型 $scope.banci = [{ id: '1' }, { id: '2' }]; $scope.myModel = { banci: [{}, {}] // 每个元素对应一个账户的表单数据 }; $scope.addNewChoice = function () { if ($scope.banci.length === 6) { return; } else { var newItemNo = $scope.banci.length + 1; $scope.banci.push({ 'id': newItemNo.toString() }); // 同步添加模型项,保持数据和视图一致 $scope.myModel.banci.push({}); } }; $scope.removeChoice = function (index) { // 删除指定索引的项,精准操作当前表单 $scope.banci.splice(index, 1); $scope.myModel.banci.splice(index, 1); }; }]);
第二步:修正HTML视图代码
重点修改控件的name、ng-model绑定,以及验证表达式:
<fieldset data-ng-repeat="(index, banca) in banci track by banca.id"> <legend> Conturi bancare </legend> <ng-form name="userFieldForm"> <!-- 账户号输入框 --> <div class="form-group" ng-class="{'has-error': userFieldForm['contbanca' + index].$dirty && userFieldForm['contbanca' + index].$invalid, 'has-success': userFieldForm['contbanca' + index].$valid}"> <div class="col-md-4"> <label class="control-label"> Cont banca {{index + 1}} <span class="symbol required"></span> </label> <input type="text" placeholder="Nr. Cont..." class="form-control" name="contbanca{{index}}" ng-model="myModel.banci[index].contbanca" ng-pattern="/[a-zA-Z0-9]{24}/" required/> <span class="error text-small block" ng-if="userFieldForm['contbanca' + index].$dirty && userFieldForm['contbanca' + index].$error.required">Va rugam inserati numarul de cont!</span> <span class="error text-small block" ng-if="userFieldForm['contbanca' + index].$dirty && userFieldForm['contbanca' + index].$error.pattern">Numarul de cont trebuie sa aiba 24 de caractere alfanumerice!</span> <span class="success text-small block" ng-if="userFieldForm['contbanca' + index].$valid">Contul este valid!</span> </div> </div> <!-- 银行选择下拉框 --> <div class="form-group" ng-class="{'has-error': userFieldForm['banca' + index].$dirty && userFieldForm['banca' + index].$invalid, 'has-success': userFieldForm['banca' + index].$valid}"> <div class="col-md-4"> <label for="form-field-select-{{index}}"> Banca <span class="symbol required"></span> </label> <select class="form-control" name="banca{{index}}" ng-model="myModel.banci[index].banca" required> <option value="" disabled selected>Selectati banca </option> <option value="AlphaBank">Alpha Bank</option> <option value="AngloRomanianBank">Anglo-Romanian Bank</option> <option value="ATEBank">ATE Bank</option> <option value="BancaCRFirenze">Banca C.R. Firenze</option> <option value="BancaComercialaCarpatica">Banca Comerciala Carpatica</option> <option value="EximBank">Exim Bank</option> <option value="BancaDiRoma">Banca Di Roma</option> <option value="BancaItaloRomena">Banca Italo Romena</option> <option value="BancaRomaneasca">Banca Romaneasca</option> <option value="BancaTransilvania">Banca Transilvania</option> <option value="Bancpost">Bancpost</option> <option value="BCR">BCR</option> <option value="BRD">BRD - Groupe Societe Generale</option> <option value="CEC">CEC Bank</option> <option value="CitiBank">Citibank</option> <option value="CreditEuropeBank">Credit Europe Bank</option> <option value="EgnatiaBank">Egnatia Bank</option> <option value="EmporikiBank">Emporiki Bank</option> <option value="GarantiBank">Garanti Bank</option> <option value="HVBLocuinte">HVB Locuinte</option> <option value="INGBank">ING Bank</option> <option value="LaCaixa">La Caixa</option> <option value="LeumiBank">Leumi Bank</option> <option value="LibraBank">Libra Bank</option> <option value="MarfinBank">Marfin Bank</option> <option value="MilleniumBank">Millenium Bank</option> <option value="MKBRomexterraBank">MKB Romexterra Bank</option> <option value="OTPBank">OTP Bank</option> <option value="PiraeusBank">Piraeus Bank</option> <option value="PorscheBank">Porsche Bank</option> <option value="ProCreditBank">Pro Credit Bank</option> <option value="RaifaissenBank">Raifaissen Bank</option> <option value="RaifaissenLocuinte">Raifaissen Locuinte</option> <option value="RBS">RBS</option> <option value="RomanianInternationalBank">Romanian International Bank</option> <option value="SanpaoloImiBank">Sanpaolo Imi Bank</option> <option value="UniCreditTiriacBank">Unicredit Tiriac Bank</option> <option value="Volksbank">Volksbank</option> </select> <span class="error text-small block" ng-if="userFieldForm['banca' + index].$dirty && userFieldForm['banca' + index].$error.required">Va rugam selectati banca.</span> <span class="success text-small block" ng-if="userFieldForm['banca' + index].$valid">Banca selectata!</span> </div> </div> <!-- 货币选择下拉框 --> <div class="form-group" ng-class="{'has-error': userFieldForm['moneda' + index].$dirty && userFieldForm['moneda' + index].$invalid, 'has-success': userFieldForm['moneda' + index].$valid}"> <div class="col-md-3"> <label for="form-field-select-moneda-{{index}}"> Moneda <span class="symbol required"></span> </label> <select class="form-control" name="moneda{{index}}" ng-model="myModel.banci[index].moneda" required> <option value="" disabled selected>Selectati moneda </option> <option value="LEI">LEI</option> <option value="EURO">EURO</option> <option value="USD">USD</option> </select> <span class="error text-small block" ng-if="userFieldForm['moneda' + index].$dirty && userFieldForm['moneda' + index].$error.required">Va rugam selectati moneda.</span> <span class="success text-small block" ng-if="userFieldForm['moneda' + index].$valid">Moneda selectata!</span> </div> </div> <div class="col-md-1" style="margin-top: 22px;"> <input type="button" value="X" class="btn btn-danger" ng-click="removeChoice(index)" /> </div> </ng-form> </fieldset> <button class="btn btn-primary" ng-click="addNewChoice()" ng-disabled="banci.length === 6">Adauga cont bancar</button>
关键改动说明
- 用数组管理模型:
myModel.banci数组里的每个对象对应一个账户的所有数据,确保每个表单项的模型完全独立。 - 唯一的控件name:每个控件的name都拼接了
index,比如contbanca{{index}},这样每个控件在userFieldForm里都是独立的键,验证状态不会冲突。 - 精准删除逻辑:删除按钮传递当前项的
index,控制器根据索引删除对应的列表项和模型项,避免数据不一致。 - track by优化渲染:
ng-repeat里加上track by banca.id,可以避免AngularJS在添加删除项时出现重复渲染的问题。
这样修改后,每个动态生成的表单项都会有独立的验证状态,不会再出现同步的问题,模型数据也能正确存储每个账户的信息啦!
内容的提问来源于stack exchange,提问作者Cristian Baciu
相关产品推荐
相关产品推荐

