javascript - Custom expiration date directive throwing rootScope digest error -


i have 2 input fields need validated after both fields have been entered. it's credit card expiration date, theres month , year. i'm using third-party service validation.

therefore, setup 3 directives: exp, expmonth, , expyear.

i use $watch validate user input - show error if validation false. when attempt ng-class exampleform.$error.expiry, error: [$rootscope:infdig] 10 $digest() iterations reached.

here demo 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);               };             };           };          }]); 

the problem setting validity error jquery selection line:

parentform.$setvalidity('expiry', valid, $element); 

then watching jquery element via ng-class when have:

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

in markup. causes strange exceptions thrown when angular tries deep copy value.

instead, change use .length property of jquery object instead. if non-zero (truthy), is-invalid class set correctly, otherwise won't be.

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

you ...expiry.length > 0 if makes more sense , future developers have @ code.

i forked plunkr works change.


Comments