Reputation:
I have a "uniqueCheck" directive which checks if the value is already present in a list or not and accordingly validates the ngModel. This directive when used on say an input tag works as expected but when used on a directive which renders an input tag the result is not as expected.
The validator function inside the directive is getting called but it doesn't validate or invalidate the ngModel of the input.
You can view the complete code of the directives on the plnkr link provided
Plnkr Link : plnkr
html is as follows :
<--! when used with a 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>
Upvotes: 2
Views: 655
Reputation: 4573
You're creating 2 separate ngModel
instances, that are both updated when the input's changed.
The first is created by the <input>
itself, which is the one assigned to 'myform'. This is the one that the <span>
error message within my-wrapper
is bound too.
The second one is the one created by the my-wrapper
directive - which is the one that 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 can see that the ngModel
associated with the validator, is not the same ngModel
that's associated with the form. But that both are actually being updated when the input's changed.
Clear the console once the page has loaded and then check the output when you change the first input.
http://plnkr.co/edit/nz6ODOVpn6lJlb055Svs?p=preview
Why is this happening?
Because both ng-model
directives get passed the same string ('values.abc'), which are then evaluated against scope to determine which object property they should watch and update - i.e two way binding.
So when you change the input you're changing the value of scope.values.abc
through the inputs ngModel
instance. This change is picked up by the my-wrapper
ngModel
instance - as it's watching the same object property - that then validates itself.
You can't solve the problem in this way, as the ngModel
directive expects a string, not another ngModel
instance.
Solution
You could transfer the attributes from my-wrapper
to the input
at compile:
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
Upvotes: 2
Reputation: 1704
Dont use scope in your myWrapper directive, it creates a separate scope of variables. Also, you need to use element.ngModel, not just a string 'ngModel' as the ng-model.
Change your myWrapper directive like this to work:
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' : '='}
}
});
Upvotes: 0