Angular does not assign the ng-invalid-class to the input

In order to register custom validation methods for custom form elements, we use extra directives as shown below:

<ng-form name="validatorTestForm">
    <our-input-directive name="validatorTest"
                         ng-model="ourModel"/>
    </our-input-directive>
    <our-validator-directive name="validatorTest"
                             form="validatorTestForm"
                             ng-model="ourModel">
    </our-validator-directive>
</ng-form>

These directives receive information through attributes specifying the input and form to validate. The connection is established by initializing the directive using a stripped-down version like this:

registerValidator(ourModel.form, 'validatorTest');

function registerValidator(form, inputName) {
    var validationModel = form[inputName];

    validationModel.$validators.testValidator = function (modelValue) {
        // Validate to true when more than two characters are entered
        return modelValue.length > 2;
    };
}

The our-input-directive is straightforward:

angular.directive('ourInputDirective', function() {
    return {
        restrict: 'E',
        template: '<input type="text" ng-model="model">',
        scope: {
            model: '=?ngModel'
        }
    }
});

Upon running the code, Angular appends numerous CSS classes to the form and input elements. When something is entered into the input field, the validation is triggered correctly. The form element is assigned the 'ng-valid' class if valid, and 'ng-invalid' if not.

However, the input only receives the 'ng-valid' class and never changes to invalid.
Why does this happen and how can we make it reflect the model changes on the input's CSS classes?


We aim to utilize the 'ng-invalid' class to style the input accordingly.

Answer №1

Check out the ng-model directive documentation here

The ngModel directive in AngularJS is responsible for:

  • Connecting the view to the model, as required by other directives like input, textarea, or select.
  • Handling validation behaviors such as required fields, numbers, emails, and URLs.
  • Maintaining the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
  • Applying relevant CSS classes to the element (ng-valid, ng-invalid, ng-dirty, ng-pristine, ng-touched, ng-untouched, ng-empty, ng-not-empty) including animations.
  • Registering the control with its parent form.

You can see a working example on Plnkr following this link: https://plnkr.co/edit/yWlZln2TekdCAhrZ6iEG?p=preview

function customValidator() {
   var directive = {
      require: '^form',
      link: link
   };
   return directive;

   function link(scope, element, attrs, formCtrl) {
      modelCtrl = formCtrl[attrs['name']];
      modelCtrl.$validators.testValidator = function(modelValue, viewValue) {
        var value = modelValue || viewValue;
        if(modelCtrl.$isEmpty(value)) {
          return false;
        }
        return value.length > 2;
      };
   }
}

Answer №2

In accordance with krutkowski86's suggestion, consider utilizing the ng-model directive instead of your current method. Here is an example:

<ng-form name="validatorTestForm">
    <input type="text" name="validatorTest" ng-model="MyVar" validator/>
</ng-form>

angular.module('yourModule').directive('validator', validator);

function validator() {
   var directive = {
      require: 'ngModel',
      link: link
   };
   return directive;

   function link(scope, element, attrs, ngModel) {
      ngModel.$validators.testValidator = function (modelValue) {
      // Return true if more than two characters are entered
      return modelValue.length > 2;
      };
   }
}

For a demonstration, please refer to my Plunker here.

Answer №3

Upon conducting several tests, we were able to identify the issue:

It was discovered that the 'our-validator-directive' was utilizing the ngModel of the input; however, it was not actually using the instance of the ngModel! This was due to an isolated scope within the directive that encapsulates the input. (This aspect was unintentionally omitted in the example, as it was not perceived as a problem...) Consequently, modifications made to the ngModel of the 'our-validator-directive' were not being propagated to the original one.

Connecting to the original ngModel is imperative, and can be easily achieved with:

ngModelCtrl = form[nameOfTheInput]

Rather than relying on the provided ngModel that is passed into the validators directive.

[ I have edited the example for clarity. ]

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

Passing data from the controller to the $resource object in Angular with the MEAN stack

After several attempts to troubleshoot my issue with passing parameters to the Express server, it turns out the problem lies on the Angular side. When I manually inserted the id in the flConstruct.js function, the query worked correctly. It appears that ...

Display the preloaded element as the first item using Javascript

Is there a way to prioritize the loaded elements using JavaScript? I have an array of elements that I pass to a function and make an AJAX call. While the data is loading, I display a loader (.gif). I want to ensure that the loaded elements are shown first ...

Having trouble accessing variables using the put method in Laravel with XMLHttpRequest

I am struggling to save my image data using XMLHttpRequest. Although I can send json data and see them in the developer console, I am unable to access them on the server side as the $request appears to be null. Below are snippets of my JavaScript code: ...

"Embedding a Highcharts web chart within a pop-up modal window

I am looking to incorporate a Highcharts web chart onto a specific part of a Bootstrap modal, while ensuring the size remains dynamic along with the modal itself. Here's what I have attempted so far: Sample HTML code: <td><a href="#">${ ...

When utilizing the dispatch function with UseReducer, an unexpected error is triggered: Anticipated 0 arguments were provided,

Having trouble finding a relevant answer, the only one I came across was related to Redux directly. So here's my question that might be obvious to some of you. In my code, everything appears to be correct but I'm facing an error that says: Expect ...

Copy data from JSON file to Vue2 Google Maps markers

I recently started working on a basic Vue project. The project involves integrating a Google Map using the vue2-google-maps package. Additionally, I have a JSON file (or data.php) containing the following information: { "locations": [ { "nam ...

Navigating the techniques of filtering an object with an array

I am looking to filter this object using the aaData array in order to display only unique values. For example, if the first item has the name "testowy2" and the second and third have the name "testowy", I want to show only one instance of "testowy". var j ...

Enhancing Performance of D3 JS for Visualizing Large XML Data

I am working on visualizing a large XML file, almost 1 GB in size, as a graph of nodes and links using D3 Javascript. I am currently working with mac 10.5.8. I have successfully extracted the content of the file, displaying it as: [Object Element]. The p ...

A simple guide to fetching JSON data and storing it in a variable, then parsing it and displaying it

I am looking to retrieve JSON data from the Yahoo Finance API, store it in a JavaScript variable, extract specific information such as "name" and "price", and then display it in an HTML table. The JSON data can be accessed via the following link: Current ...

What is the best way to dynamically pass JSON object values to PHP?

Greetings, I am new to JSON and Ajax. Although my question may seem trivial, I believe that even the simplest inquiries are crucial in the learning process. My dilemma involves passing two parameters (giorno and periodo) via Ajax: For example: 'gior ...

Is there a way to instantly show the contents of a newly opened tab in BootstrapVue?

Good day, my objective is as follows: Whenever a new tab is opened, it should become 'active' and display its content on the browser Issue: Currently, when a new tab is opened, the previous tab remains 'active'. Check out a simple e ...

"Encountered an error when attempting to load a resource in Node

I'm currently taking a tutorial to learn Node and Angular. Coming from a LAMP stack environment, this new world feels overwhelming and confusing. Although I have installed Angular JS and included it in my HTML file, I keep encountering the following ...

Running a Python script through a Javascript event

I'm looking to enhance my webpage by implementing a feature where users can generate a personalized QR code with the click of a button. My current setup involves a Python script that creates the QR code image and saves it as a .png file. I want to int ...

What is the best way to dynamically adjust the top CSS of an element when it is positioned at the top or

Is there a way to dynamically set the top CSS when an element is over the top or bottom of a page? First, hover over the first cat image. It's working fine. http://image.ohozaa.com/i/480/7YpWei.jpg When I scroll the page to the bottom and hover ove ...

Calculate the number of elements in a given array within a specific document

I'm in the process of setting up a blog where each post consists of multiple paragraphs. My goal is to be able to count the number of paragraphs in a specific post. The structure of my "Blog" collection, which contains documents (posts), looks like th ...

"An error occurred with the Google chart due to 'null' not being recognized as an object, specifically in relation to the select menu and onchange event

Currently, I have implemented the following Script: <header> <script type="text/javascript" src="http://www.google.com/jsapi"></script> </header> <body> <script type="text/javascript"> google.load("visualization", "1 ...

What is the best way to initiate a Bootstrap carousel so that it begins with the first image every time a modal window appears

I am in the process of creating my own portfolio to showcase my work. I have implemented a feature where clicking on an image opens up a Bootstrap carousel. However, I'm facing an issue where the carousel doesn't always start with the first imag ...

Handle changes to input values on ng-click even if they were made outside of Angular's control

Looking to pass input values on ng-click even when they are changed outside of Angular. Everything works fine when manually typing, but once the inputs have dynamic values, ng-click passes empty form data. Below is the HTML code snippet: <form id="form ...

Encountering difficulties accessing Node.JS Sessions

Hey there, I am currently working on integrating an angular application with Node.js as the backend. I have set up sessions in Angular JS and created my own factory for managing this. Additionally, I am utilizing socket.io in my Node.js server and handling ...

Unusual marker appearing on every page utilizing ionic v1 and angularjs

For some unknown reason, a dot appears at the upper left side of each page in my webapp: https://i.stack.imgur.com/nN61t.png It seems to be an issue with the HTML code. When I run the snippet below, the dot is visible: <ion-view view-title="Send fe ...