AngularJS ng-repeat表格上方展示验证错误问题求助
解决AngularJS ng-repeat表格中统一显示验证错误的问题
我之前处理过类似的AngularJS表单验证场景,你的核心痛点在于ng-repeat循环中重复的表单控件name属性导致父表单无法正确追踪每个控件的验证状态——父表单里同名的控件会被覆盖或变成数组,根本没法精准判断哪一行的输入出了问题。下面是具体的解决方案,一步步帮你搞定:
1. 为每行创建独立的行级表单
首先要给ng-repeat的每行绑定一个独立的表单对象,这样每个输入控件的验证状态都会被单独记录。你之前试过加ng-form但没生效,大概率是没把行表单的引用收集起来,没法在父容器里判断全局错误。
修改表格行的代码,把行表单绑定到控制器里的数组:
<form name="equipmentDuplicatesForm" novalidate> <!-- 错误提示区域放在这里 --> <table> <tbody infinite-scroll="loadMore()"> <tr ng-repeat="row in duplicatesArray" ng-click="selectedDuplicateIndex=$index;" ng-class="{selected: $index === selectedDuplicateIndex}" ng-form="rowForms[$index]"> <!-- 将行表单存入数组 --> <!-- 省略其他单元格 --> <td> <div class="col-xs-12"> <input type="text" name="assetNo" ng-model="row.assetNo" class="form-control" ng-change="checkAssetNo(row)" ng-maxlength="100" sm-duplicate-validator validate-duplicates="true" error-message="row.errorMessage" api-method="api/rentalEquipments/checkForDuplicate" primary-key-value="row.equipmentId" ng-model-options="{ debounce: { default : 500, blur: 0 }}" /> </div> </td> <td> <input type="text" name="serialNo1" ng-model="row.serialNo1" class="form-control" ng-maxlength="100" /> </td> </tr> </tbody> </table> </form>
注意:去掉循环中input的重复id属性(比如你之前的id="assetNo"),HTML里id必须唯一,重复id会导致DOM选择器混乱。
2. 在控制器中收集并判断全局错误状态
在控制器里定义一个数组存储所有行表单,再写几个工具函数判断是否存在任意一行的验证错误:
$scope.rowForms = []; // 存储每行的表单对象 // 判断是否存在任何错误(用于控制错误提示区域的显示) $scope.hasAnyError = function() { return $scope.hasAnyDuplicateError() || $scope.hasAnyAssetNoMaxlengthError() || $scope.hasAnySerialNoMaxlengthError(); }; // 判断是否有资产编号超长 $scope.hasAnyAssetNoMaxlengthError = function() { return $scope.rowForms.some(function(form) { return form && form.assetNo && form.assetNo.$error.maxlength; }); }; // 判断是否有序列号超长 $scope.hasAnySerialNoMaxlengthError = function() { return $scope.rowForms.some(function(form) { return form && form.serialNo1 && form.serialNo1.$error.maxlength; }); }; // 判断是否有重复错误 $scope.hasAnyDuplicateError = function() { return $scope.rowForms.some(function(form) { return form && form.assetNo && (form.assetNo.$error.smDuplicate || form.assetNo.$error.duplicate); }); }; // 删除行时同步维护行表单数组 $scope.removeRow = function(index) { $scope.duplicatesArray.splice(index, 1); $scope.rowForms.splice(index, 1); };
3. 调整错误提示区域的逻辑
把原来的错误提示区域改成用上面的工具函数判断显示,这样就能在表格上方统一展示全局错误:
<div class="col-xs-12" ng-show="hasAnyError()"> <div class="info-text-block info-text-block-error"> <p ng-show="hasAnyDuplicateError()"> {{getDuplicateError()}} </p> <p ng-show="hasAnyAssetNoMaxlengthError()"> @string.Format(Messages.cannotExceed, Labels.assetNo, "100") </p> <p ng-show="hasAnySerialNoMaxlengthError()"> @string.Format(Messages.cannotExceed, Labels.serialNo1, "100") </p> </div> </div>
4. 确保自定义重复验证指令正确标记行级错误
你的sm-duplicate-validator自定义指令需要确保错误状态标记在当前行的表单控件上,而不是父表单。指令核心逻辑大概是这样的(如果还没调整的话):
app.directive('smDuplicateValidator', function($http, $q) { return { require: 'ngModel', scope: { validateDuplicates: '=', apiMethod: '@', primaryKeyValue: '@' }, link: function(scope, element, attrs, ngModel) { // 异步验证逻辑 ngModel.$asyncValidators.smDuplicate = function(modelValue, viewValue) { if (!scope.validateDuplicates || !modelValue) { return $q.resolve(); } return $http.post(scope.apiMethod, { value: modelValue, primaryKey: scope.primaryKeyValue }).then(function(response) { return response.data.isDuplicate ? $q.reject('duplicate') : $q.resolve(); }); }; } }; });
这个指令会把重复错误标记到当前行表单的assetNo控件上,这样rowForms[$index].assetNo.$error.smDuplicate就能正确返回状态。
内容的提问来源于stack exchange,提问作者Naomi
相关产品推荐
相关产品推荐

