2

我需要ng-form="myForm"根据范围变量启用/禁用 Angular 表单或子表单中的所有验证规则$scope.isValidationRequired。因此,如果isValidationRequiredfalse,则为指定字段组设置的任何验证都不会运行,结果将始终为myForm.$valid==true,否则,验证规则将照常运行。

我做了很多研究,并意识到这个功能在 Angular 中是不可用的。但是,我发现了一些附加组件或进行了一些自定义,这是可能的。

例如,我可以使用带有自定义指令的附加angular-conditional-validationgithubdemoenable-validation="isValidationRequired" ) 。这将是完美的,除了我不能将此功能应用于ng-form. 我必须为每个适用的字段添加此指令。

另一种解决方案是使用 Angular$validators管道使用自定义验证。这需要一些额外的努力,而且我没有时间,因为 sprint 快结束了,我必须在几天内给出一些结果。

如果您有任何其他建议,请发布答案。

用例:

为了澄清这一点,我将提到用例。最终用户可以用无效数据填写表单,他可以单击Save按钮,在这种情况下,不应该触发验证规则。只有当用户单击时,才Validate and Save应触发验证规则。

解决方案:

在此处查看最终的 plunker 代码。

更新:根据下面的评论,如果在ng-form. 需要更多的努力来调试和解析这个发行者。如果只使用一个级别,那么它工作正常。

更新:这里的 plunker更新了更通用的解决方案。现在该代码将使用具有子表单的表单ng-form。该函数setAllInputsDirty()检查对象是否$$parentForm为停止递归。此外,changeValidity()将检查对象是否是一个表单,$addControl然后它将调用自身来验证其子对象。到目前为止,这个函数运行良好,但它需要一些额外的优化。

4

2 回答 2

1

一种想法是如果禁用验证标志,则重置摘要循环中的错误。您可以遍历更改时的表单错误并将它们一一设置为有效。

$scope.$watch(function() {
    $scope.changeValidity();
}, true);

$scope.changeValidity = function() {
    if ($scope.isValidationRequired === "false") {
        for (var error in $scope.form.$error) {
            while ($scope.form.$error[error]) {
                $scope.form.$error[error][0].$setValidity(error, true);
            }
        }
    }
}

这是一个 plunkr:https ://plnkr.co/edit/fH4vGVPa1MwljPFknYHZ

于 2016-10-21T01:16:30.460 回答
0

这是将防止无限循环和无限递归的更新答案。此外,代码依赖于已知的根形式,可以稍微调整以使其更通用。

参考:Pixelastic 博客Larry 的回答
Plunker:https
://plnkr.co/edit/ycPmYDSg6da10KdoNCiM?p=preview 更新:代码改进使其适用于每个子表单中每个字段的多个错误,并循环确保错误被​​清除在子表单级别

var app = angular.module('plunker', []);
app.controller('MainCtrl', ["$scope", function($scope) {
  $scope.isValidationRequired = true;
    var rootForm = "form";
    function setAllInputsDirty(scope) {
        angular.forEach(scope, function(value, key) {
            // We skip non-form and non-inputs
            if (!value || value.$dirty === undefined) {
                return;
            }
            // Recursively applying same method on all forms included in the form except the parent form
            if (value.$addControl && key !== "$$parentForm") {
                return setAllInputsDirty(value);
            }
            if (value.$validate){
                value.$validate();
            }
            // Setting inputs to $dirty, but re-applying its content in itself
            if (value.$setViewValue) {
                //debugger;
                return value.$setViewValue(value.$viewValue);
            }
        });
    }

  $scope.$watch(function() {
    $scope.changeValidity();
}, true);

    $scope.changeValidity = function(theForm) {
        debugger;
        //This will check if validation is truned off, it will 
        // clear all validation errors
        if (!theForm) {
          theForm = $scope[rootForm];
        }
        if ($scope.isValidationRequired === "false") {
            for (var error in theForm.$error) {
                errTypeArr = theForm.$error[error];
                angular.forEach (errTypeArr, function(value, idx) {
                    var theObjName = value.$name;
                    var theObj = value;
                    if (theObj.$addControl) {
                        //This is a subform, so call the function recursively for each of the children
                        var isValid=false;
                        while (!isValid) {
                            $scope.changeValidity(theObj);
                            isValid = theObj.$valid;
                        }
                    } else {
                      while (theObj.$error[error]) {
                          theObj.$setValidity(error, true);
                      }
                    }
                })
            }
        } else {
            setAllInputsDirty($scope);
        }
    }

}]);
于 2016-10-26T14:17:31.160 回答