1

У меня есть 2 поля ввода, которые должны быть проверены после ввода обоих полей. Это срок действия кредитной карты, поэтому theres month и year. Я использую стороннюю службу для фактической проверки.Пользовательская директива даты истечения срока действия ошибки rootScope digest

Поэтому я устанавливаю 3 директивы: exp, expMonth и expYear.

Я использую $watch для проверки ввода пользователя - однако я хотел бы показать ошибку, если проверка является ложной. Когда я пытаюсь сделать ng-class с exampleForm.$error.expiry, я получаю 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); 
       }; 
      }; 
      }; 

     }]); 
+0

Когда вы получаете исключение бесконечного исключения, оно также регистрирует последние выражения _x_ watch, оцениваемые в консоли. Можете ли вы опубликовать этот список? Кроме того, если вы можете воспроизвести это в [Plunkr] (http://plnkr.co) или каком-либо другом таком инструменте, это было бы полезно для нас, чтобы диагностировать. – GregL

+0

Несколько других комментариев: 1) Какую версию AngularJS вы используете? 2) Я предполагаю, что в вашей разметке директивы на самом деле являются «exp-month» и 'exp-year' (не верблюд, как у вас было). 3) Если вы регистрируете аргументы функции 'setValidity()', что вы замечаете о различии между новым значением (1-й аргумент) и старым значением (2-й аргумент)? – GregL

+0

Добавлен plunkr. http://plnkr.co/edit/SSiSfLB8hEEb4mrdgaoO?p=preview – cusejuice

ответ

1

Проблема в том, что вы устанавливаете ошибку действия для выбора Jquery с линией :

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

Тогда вы смотрите, что JQuery элемент через ng-class, когда у вас есть:

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

в разметке. Это заставляет странные исключения бросать, когда угловой пытается глубоко скопировать это значение.

Вместо этого измените его, чтобы вместо этого использовать свойство .length объекта jQuery. Если ненулевой (правдивый), класс is-invalid будет установлен правильно, иначе его не будет.

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

Вы также можете сделать ...expiry.length > 0, если это имеет смысл для вас и будущих разработчиков, которые должны смотреть на ваш код.

I forked your Plunkr поэтому он работает с этим изменением.

+0

Большое вам спасибо. Делает много смысла. – cusejuice