自定义到期日期指令抛出 rootScope 摘要错误

Custom expiration date directive throwing rootScope digest error

我有 2 个输入字段需要在输入两个字段后进行验证。这是信用卡到期日,所以有 monthyear。我正在使用第三方服务来实际进行验证。

因此,我设置了 3 个指令:expexpMonthexpYear

我使用 $watch 来验证用户输入 - 但是如果验证为假,我想显示错误。 当我尝试用 exampleForm.$error.expiry 执行 ng-class 时,我得到 Error: [$rootScope:infdig] 10 $digest() iterations reached.

这是一个演示 http://plnkr.co/edit/SSiSfLB8hEEb4mrdgaoO?p=preview

view.html

  <form name='exampleForm' novalidate>
    <div class="form-group" ng-class="{ 'is-invalid': exampleForm.$error.expiry }">
       <div class="expiration-wrapper" exp>
          <input type='text' ng-model='data.year' name='year' exp-month />
          <input type='text' ng-model='data.month' name='month' exp-year />
       </div>
    </div>

exp.directive.js

  angular.module('example')
    .directive('exp', ['ThirdPartyValidationService',
      function(ThirdPartyValidationService) {
        return {
          restrict: 'A',
          require: 'exp',
          link: function(scope, element, attrs, ctrl) {
            ctrl.watch();
          },
          controller: function($scope, $element, ThirdPartyValidationService) {
            var self = this;
            var parentForm = $element.inheritedData('$formController');
            var ngModel = {
              year: {},
              month: {}
            };

            var setValidity = function(exp) {
              var expMonth = exp.month;
              var expYear = exp.year;
              var valid = ThirdPartyValidationService.validateExpiry(expMonth, expYear);

              parentForm.$setValidity('expiry', valid, $element);
            };

            self.setMonth(monthCtrl) {
              ngModel.month = monthCtrl;
            };

            self.setYear(yearCtrl) {
              ngModel.year = yearCtrl;
            };

            self.watch = function() {
              $scope.$watch(function() {
                return {
                  month: ngModel.month.$modelValue,
                  year: ngModel.year.$modelValue
                };
              }, setValidity, true);
            };
          }
        };
      }]);

expMonth.directive.js

    angular.module('example')
      .directive('expMonth', [
        function() {
          return {
            restrict: 'A',
            require: ['ngModel', '^?exp'],
            compile: function(element, attributes) {
              return function(scope, element, attributes, controllers) {

                var formCtrl = controllers[0];
                var expMonthCtrl = controllers[1];

                expMonthCtrl.setMonth(formCtrl);
              };
            };
          };

        }]);

expYear.directive.js

    angular.module('example')
      .directive('expYear', [
        function() {
          return {
            restrict: 'A',
            require: ['ngModel', '^?exp'],
            compile: function(element, attributes) {
              return function(scope, element, attributes, controllers) {

                var formCtrl = controllers[0];
                var expYearCtrl = controllers[1];

                expYearCtrl.setYear(formCtrl);
              };
            };
          };

        }]);

问题是您将有效性错误设置为 jquery 选择行:

parentForm.$setValidity('expiry', valid, $element);

然后您通过 ng-class 观看 jQuery 元素,当您有:

ng-class="{ 'is-invalid' : exampleForm.$error.expiry }"

在您的标记中。这会导致在 angular 尝试深度复制此值时抛出奇怪的异常。

改为使用 jQuery 对象的 .length 属性。如果非零(真实),is-invalid class 将被正确设置,否则不会。

ng-class="{ 'is-invalid' : exampleForm.$error.expiry.length }"

如果这对您和未来必须查看您的代码的开发人员更有意义,您也可以这样做 ...expiry.length > 0

forked your Plunkr 所以它适用于此更改。