Error with custom expiration date directive causing rootScope digest error

There are 2 input fields that need validation after both have been filled out: the credit card expiration date consisting of a month and year. A third-party service is used for the validation process.

To handle this, 3 directives are set up: exp, expMonth, and expYear.

A $watch function is implemented to validate user input. However, displaying an error when validation fails proves to be challenging. When attempting to use ng-class with exampleForm.$error.expiry, an error message is returned:

Error: [$rootScope:infdig] 10 $digest() iterations reached.

Here is a 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);
              };
            };
          };

        }]);

Answer №1

The issue arises from assigning the validity error to a jQuery selection with this line of code:

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

Subsequently, you are monitoring that jQuery element using ng-class in your markup like so:

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

This results in angular encountering abnormal exceptions when attempting to copy this value deeply.

To resolve this, modify it to utilize the .length property of the jQuery object instead. If it is non-zero (truthy), the is-invalid class will be applied correctly; otherwise, it won't.

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

Alternatively, you could use ...expiry.length > 0 if that makes more sense to you and any future developers examining your code.

I have modified your Plunker to accommodate this change.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with ngModel value not being accurately represented by checkbox state in Angular 2

My issue lies with a checkbox that does not reflect its ngModel value. To provide some context, I have a Service managing a list of products and a component responsible for displaying this list and allowing users to select or deselect products. If a user d ...

Tips for showing an empty string in an Angular expression when the value is equal to zero

<div>{{a.value | number:0}}</div> I currently have this code snippet. Is there a way to display only empty quotes if the value is 0 directly within the same line? Or do I need to filter it out in a controller? Thank you for your help! ...

Require field change in SharePoint 2010

I have implemented the following code on a SharePoint page - it locates the specified select based on its title and triggers an alert when the "Decision" value is selected. I am interested in removing the alert and instead substituting with code that iden ...

I would appreciate it if someone could clarify how the rendering process occurs in React in this specific scenario

let visitor = 0; function Mug({name}) { visitor = visitor + 1; console.log(name, visitor); return <h2>Coffee mug for visitor #{visitor}</h2>; } return ( <> <Mug name={"A"}/> <Mug name={"B&qu ...

Using the i18next Module for Localization in ExpressJS and Front-End Development

I am currently integrating the i18next module into my NodeJs/ExpressJS web application. All the translation files are stored in the /locales directory. According to information from i18next.com, it can also be utilized on the client side. <script typ ...

Using AngularJS to incorporate ng-include with ng-click functionality

I am trying to figure out a way to insert HTML that is specifically optimized for the controller into an alert div. Unfortunately, I have been unsuccessful so far... <script type="text/ng-include" id="login.html"> <form data-select="exepti ...

Implementing a text-based "continue" button on an R Shiny DataTable with Bootstrap design

By default, Shiny DT displays buttons to navigate through records. However, when using style="bootstrap", these buttons change to text, "previous12345...8Next" while still functioning as clickable links. How can I ensure that the buttons are re ...

AngularJS secondary controller experiencing malfunctions

Having an issue with my second controller (RegisterController) in the module I've created. The first one is working perfectly fine. I have both controllers in a file named user.js var app = angular.module("User", []); app.controller('LoginCont ...

How to use a function as the redirectTo parameter in Angular 2+ routing

In my Angular application, I have set up the following route configuration: { path: ParentComponent.path, component: ParentComponent, canActivate: [AuthGuard], children: [ { path: '', pathMatch: 'full', re ...

Importing third-party JavaScript libraries and modules in AngularJS

I'm curious about the impact on performance when loading External JS files in Angular JS. Specifically, I have a small module that utilizes tinymce editor installed through bower ('angular-ui-tinymce') and it works well. Given that this lib ...

Issues with JavaScript scripts functionality on my live server

Hey everyone, I'm new to this community and having some trouble with my index.html file. Everything works fine except for one script that only runs when I open the file directly with live server in VSCode. Can someone help me out? The script causing i ...

The ng-repeat-start feature is not functioning properly across different levels

I am attempting to utilize the ng-repeat-start directive in order to construct a table that resembles the following: https://i.sstatic.net/Qgc91.png The structure of my JSON data is as follows: [ { "name": "Chapter 1", "parts": [ { ...

JavaScript increase numbers in an array

We are dealing with a numerical array where each element has its maximum value. How can we update the elements in order for the array to transition from [0, 0, 0] to [x, y, z]? For example, if the maximum array values are [2, 1, 2] and the initial array i ...

Navigating specific elements within ReactORTraversing designated components

Trying to iterate through specific elements in React to render a portion of an array for each view. The rendering of the array should start from ArrayIndexStart and end at ArrayIndexEnd. Here is the current implementation: const ObjectArray = [ {" ...

Can you help me troubleshoot an issue I am facing with the expand table in Angular 9 and JS? I am getting an

Here you can find the code demonstration and behavior: No extensive explanation is necessary. Check out the StackBlitz demo by clicking on the first row to view its details. Then, click on the second row to see how the details from the first row are repl ...

What is the best way to simulate global variables that are declared in a separate file?

dataConfiguration.js var userData = { URIs: { APIURI: "C" }, EncryptedToken: "D" }; configSetup.js config.set({ basePath: '', files:['dataConfiguration.js' ], ..... UserComponentDetails: .....some i ...

The persistence of postback from the javascript function despite returning false when utilizing Asp Radiobuttonlist

HTML: <asp:RadioButtonList ID="rdStatus" runat="server" Height="48px" RepeatDirection="Horizontal" AutoPostBack="true" OnSelectedIndexChanged="rdStatus_SelectedIndexChanged" CssClass="rad"> ...

Adjust the position of an element based on changes in window size using jQuery

Wondering if this question is unique, as I've spent quite some time searching for a solution to this issue without any luck. Perhaps my search criteria aren't correct. I have a navigation bar that becomes fixed when it reaches the top of the vie ...

Blending conditional and non-conditional styles in VueJS

Is it possible to set a class in Vue based on the value of a parameter and conditionally add another class if that parameter meets a certain condition? Can these two functionalities be combined into one class assignment? <button :class="'btn btn-p ...

Transferring information between HTML pages using JSON and jQuery

After reviewing the topics, I was unable to find a complete answer. My objective is to populate a drop-down menu with text from another HTML file. Both HTML files are located on localhost. It is mandatory for the data to be in JSON format. Initially, I a ...