angular:验证多个依赖字段

TG-*_*G-T 28 javascript validation angularjs

假设我有以下(非常简单的)数据结构:

$scope.accounts = [{
   percent: 30,
   name: "Checking"},
 { percent: 70,
   name: "Savings"}];
Run Code Online (Sandbox Code Playgroud)

然后我将以下结构作为表单的一部分:

<div ng-repeat="account in accounts">
    <input type="number" max="100" min="0" ng-model="account.percent" />
    <input type="text" ng-model="account.name" />
</div>
Run Code Online (Sandbox Code Playgroud)

现在,我想验证每组帐户的百分比总和为100,但我看到的自定义指令的大部分示例仅涉及验证单个值.创建一个可以一次验证多个依赖字段的指令的惯用方法是什么?在jquery中有相当多的解决方案,但我还没有找到Angular的良好来源.

编辑:我想出了以下自定义指令("share"是原始代码的"百分比"的同义词).share-validate指令将表单的映射"{group: accounts, id: $index}"作为其值.

app.directive('shareValidate', function() {
return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ctrl) {
        ctrl.$parsers.unshift(function(viewValue) {
            params = angular.copy(scope.$eval(attr.shareValidate));
            params.group.splice(params.id, 1);
            var sum = +viewValue;
            angular.forEach(params.group, function(entity, index) {
                sum += +(entity.share);
            });
            ctrl.$setValidity('share', sum === 100);
            return viewValue;
        });
    }
};
});
Run Code Online (Sandbox Code Playgroud)

此ALMOST有效,但无法处理字段无效的情况,但另一个字段的后续更改会使其再次有效.例如:

Field 1: 61
Field 2: 52
Run Code Online (Sandbox Code Playgroud)

如果我将Field 2降至39,则Field 2现在有效,但Field 1仍然无效.想法?

TG-*_*G-T 14

好的,以下工作(再次,"分享"是"百分比"):

app.directive('shareValidate', function () {
return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ctrl) {
        scope.$watch(attr.shareValidate, function(newArr, oldArr) {
            var sum = 0;
            angular.forEach(newArr, function(entity, i) {
                sum += entity.share;
            });
            if (sum === 100) {
                ctrl.$setValidity('share', true);
                scope.path.offers.invalidShares = false;
            }
            else {
                ctrl.$setValidity('share', false);
                scope.path.offers.invalidShares = true;
            }
        }, true); //enable deep dirty checking
    }
};
});
Run Code Online (Sandbox Code Playgroud)

在HTML中,将属性设置为"share-validate",并将值设置为要监视的对象集.

  • 很好的可行解决方案,但我会说它可以改进,使其更通用.我不认为在指令中硬编码范围路径是一个好习惯.我做了一些更通用的东西(也许它将在未来帮助你):http://liviutrifoi.wordpress.com/2013/10/19/angular-custom-validation-with-business-rules/ (5认同)
  • 嗨,你能分享上面例子的工作小提琴吗,谢谢 (2认同)

Cha*_*ani 8

您可以检查angularui库(ui-utility部分).它有ui-validate指令.

你可以实现它的一种方法是

<input type="number" name="accountNo" ng-model="account.percent"
ui-validate="{overflow : 'checkOverflow($value,account)' }">
Run Code Online (Sandbox Code Playgroud)

在控制器上创建checkOverflow基于帐户计算返回true或false 的方法.

我自己没试过,但想分享这个想法.阅读网站上的样本.

  • 我不认为ui-validate在这里工作,因为它也只验证编辑的字段.因此,如果您在两个字段中输入例如20,则它们都无效.如果您随后将其中一个更改为80,则该字段确实有效,但另一个字段仍然显示无效. (12认同)

Jas*_*ite 5

我有一个案例,我有一个动态表单,我可以在我的表单上有可变数量的输入字段,我需要限制正在添加的输入控件的数量.

我不能轻易地限制这些输入字段的添加,因为它们是由其他因素的组合生成的,所以如果输入字段的数量超过限制,我需要使表单无效.我通过在控制器中创建对表单的引用来完成此操作ctrl.myForm,然后每次动态生成输入控件(在我的控制器代码中),我都会进行限制检查,然后在表单上设置有效性,如下所示:ctrl.myForm.$setValidity("maxCount", false);

这很有效,因为验证不是由特定的输入字段决定的,而是我的输入的总体计数.如果您需要通过多个字段的组合确定需要进行的验证,则可以使用相同的方法.