Issues arise when attempting to use AngularJS validators in conjunction with another directive

I created a directive called "uniqueCheck" that validates the ngModel based on whether the value is already in a list or not. Everything works fine when the directive is used directly on an input tag. However, when used on a custom directive that contains an input tag, the validation does not behave as expected.

The validator function inside the directive is being executed, but it doesn't properly validate the ngModel of the input field.
For a complete look at the code for these directives, you can visit the Plnkr link provided.

Access the Plnkr here: plnkr

Here is an example of the HTML:

<--! when used with a custom directive -->
<my-wrapper ng-model="values.abc" unique-check="" list="list" prop="name"> </my-wrapper>

<--! when used on an input tag-->    
 <div ng-form="myform">
     <input type="text" unique-check 
        list="list" prop="name" 
        name="myfield" 
        ng-model="values.pqr"/>
  <span>isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>
</div>

Answer №1

When you create two separate instances of ngModel, they are both updated when the input changes.

The first instance is created by the <input> itself and is assigned to 'myform'. This is the one that the error message within my-wrapper is bound to.

The second instance is created by the my-wrapper directive and has the validator attached to it.

If you check the console (for the plnkr below) and inspect the values being output by the validator when the input is changed, you will see that the ngModel associated with the validator is different from the one associated with the form. However, both instances are being updated when the input changes.

Clear the console once the page has loaded and then observe the output when you change the first input.

http://plnkr.co/edit/nz6ODOVpn6lJlb055Svs?p=preview


What is the reason behind this?

Both ng-model directives are passed the same string ('values.abc'), which is then evaluated against the scope to determine the object property they should watch and update - enabling two-way binding.

So, when you change the input, you are actually changing the value of scope.values.abc through the input's ngModel instance. This change is detected by the my-wrapper ngModel instance, as it is also watching the same object property and then proceeds to validate itself.

This issue cannot be resolved in this manner, as the ngModel directive expects a string, not another ngModel instance.


Solution

You could transfer the attributes from my-wrapper to the input during compilation:

app.directive("myWrapper", function(){

    var templateFn = function(element, attrs){
        return '<div ng-form="myform">'+
                   '<input type="text" name="myfield"/>'+
                   '<span>(inside directive) : isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
               '</div>';
    }

    return {
        restrict :'E',
        template : templateFn,
        require: 'ngModel',
        scope: true,
        compile: function(element, attrs) {
            var attr;
            angular.forEach(element.find('input'), function(elem) {
                elem = angular.element(elem)
                for(attr in attrs.$attr) {
                    elem.attr(attrs.$attr[attr], attrs[attr]);
                }
            });

            for(attr in attrs.$attr) {
                element.removeAttr(attrs.$attr[attr]);
            }
        }
    }
});

http://plnkr.co/edit/m2TV4BZKuyHz3JuLjHrY?p=preview

Answer №2

Avoid using scope in your custom directive myWrapper as it will create a separate scope for variables. Instead, make sure to use element.ngModel rather than just a string 'ngModel' for the ng-model to work correctly.

Modify your myWrapper directive as shown below:

app.directive("myWrapper", function(){
    var templateFn = function(scope, element, attrs){
    return '<div ng-form="myform">'+
          '<input type="text" name="myfield" ng-model="'+element.ngModel+'"/>'+
          '<span>isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
          '</div>';
  }

  return {
      restrict :'E',
      template : templateFn,
      //require: 'ngModel',
      //scope: {'ngModel' : '='}
  }

});

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

Enhanced jQuery implementation for hiding elements

I encountered a peculiar issue where jQuery's .is(':hidden') function wrongly returned true for an element that visibly displayed content. You can see the problem demonstrated in this fiddle. The :hidden pseudo checks both offsetWidth and o ...

Dynamically insert <td> elements into <tr> element using both jQuery and JavaScript

I am facing an issue with adding a new table data (td) element dynamically to the first table row (tr) in my JavaScript code. Here is the original table before adding the new td element: <table> <tbody> <tr> <t ...

The directive does not actively monitor changes to the value attribute

Whenever I click on an input field, a color picker pops up and the selected RGBA string is written back to the input's value attribute. Initially, I believed that adding ng-model="color" to the input tag would be enough for the color variable to hold ...

Utilizing a refreshed array of elements within a component directive

When working within a view, I am utilizing ng-repeat inside a directive to iterate over an array of objects from my controller. However, as the objects in the array undergo value changes, I encounter a dilemma when transitioning to a new instance of the sa ...

Updating State Array dynamically with React JS

I am facing an issue with updating a UseState quantity array in real time. When clicking on a button, a new array is created with updated values for a specific object's quantity. However, the original array does not update immediately. Instead, it onl ...

Vuetify - Best practices for vertically aligning rows in a v-treeview component

Just getting started with Vue js, so pardon me if this is a silly question. I've scoured the internet and can't seem to find a solution. I'm working on a v-treeview displaying a folder structure, with descriptions of each folder in a separa ...

Enhance Your JSF Form Validation Using AJAX and Validator Class

For a university assignment, I am required to validate form input using AJAX and a Validator Class. While I have experience with using AJAX in JSF for filtering a list, I am unsure of how to integrate it with a validator. The validation needs to occur when ...

Tips on implementing Dropdown functionality using ng-model in Selenium WebDriver

I have been experimenting with AngularJS ng-model to create a dropdown in my Selenium WebDriver code, but I am facing issues with it not working as expected. Here is the snippet of my code: package automation.test; import java.io.File; import org.openqa.s ...

Unable to display a recursive component with Vue3 CDN

I am currently working on a project using Vue3 CDN because the project environment cannot run npm. I have been trying to create a component with html+CDN, but when attempting to create a recursive component, it only renders the top-level element. Is there ...

Ionic: Error - Unable to access the 'ready' property of an undefined object

I keep encountering this error message: TypeError: Cannot read property 'ready' of undefined Here is the snippet of my code: angular.module('app', ['ionic', 'app.controllers', 'app.routes', 'app.dir ...

Why is my custom function failing to operate on an array?

My function is created to organize and remove duplicates from a provided array. Below is an excerpt of the code: Bubble Sort - function organize(postsCollection, type, direction){ let target = postsCollection[0][type]; let swapp = false, ...

Having difficulty validating the field accurately with Angular.js

In order to validate the input field in accordance with the user's needs using AngularJS, I have shared my code below: <div ng-class="{ 'myError': billdata.longitude.$touched && billdata.longitude.$invalid }"> <input type ...

Is there a way to modify the CSS display property upon clicking a link or button?

I have a ul with the id of "menu-list". The display property is set to "none" in my CSS file, but I want it to switch to "flex" when a link is clicked. I am trying to use the click event on the link to change the display prop ...

What is the best way to navigate back to the previous state in reactjs?

I have implemented a sidebar component with its initial state set to false in order to hide the block until a user interacts with the hamburger icon. Once clicked, the state changes to true and displays the sidebar menu. However, I am facing an issue whe ...

Desktop Safari displays Font-awesome icons with trimmed corners using a border-radius of 50%

While working on incorporating font awesome share icons into my project, I encountered an issue with getting a circle around them. After exploring various approaches, I opted for a CSS solution. Using React FontAwesome posed some challenges that led me to ...

Unable to trigger a function on the button within the ng-repeat directive

As a beginner in AngularJS, I am facing an issue while working with it. My problem involves a table structure like this: ... <tr ng-repeat="line in lines"> <remove-line> <input id="line_id" type="hidden" value="{{line.id}}"> ...

Integrate a new functionality into the Express model

Imagine I have created an Express model like this: var SchemaDescription = {}; var Model = new mongoose.Schema(SchemaDescription); Data validation can be adjusted in the SchemaDescription when using Express. While it works fine on save, there is an issue ...

MEAN Project - Organizational Endeavors

Can anyone share their recommended practices for developing a Single Web Page app project using the MEAN stack (MongoDB, Express, Angular and Node.js)? Our current setup involves: One repository for the Angular client-side code Another repository for th ...

Guide on transforming 3D obj files into particles using three.js

I've been experimenting with particles in three.js, but I've encountered an issue when trying to convert an obj file (3D model) into particles. Here are the code snippets I've been working with, but so far all my attempts have failed. Does ...

What is the best way to sort ng-options in an AngularJS select element?

I am encountering a situation where I have the following code snippet: <select ng-model="person" ng-options="person.name for person in mv.people"> However, within the mv.people array, there are certain members that I need to hide. For examp ...