sergio0983 sergio0983 - 4 months ago 28
AngularJS Question

$watch ngModel not firing

I have made a directive to handle file uploads, and it works when uploading files, but not so good when preloading data because the watch on the model is not giving me the expected results.

And those areis the relevant parts of the code:

http://codepen.io/sergio0983/pen/EyLwaQ?editors=1011

the part that is causing me a headache is this one:

<div ng-app = 'app' ng-controller = 'customCtrl'>

<file ng-model = 'doc' placeholder = 'modelEmpty' required></file>
<file ng-model = 'existingDoc' placeholder = 'modelNotEmpty' ng-required></file>

<div>


JS

app.controller("customCtrl", function($scope){
$scope.existingDoc = "filename.jpg"
})

app.directive("file", function($parse){
return{
restrict:"E",
require:"?ngModel",
scope:{
ngModel:"="
},
transclude:true,
.....
link:....

scope.$watch(attrs.ngModel, function(newVal, oldVal){
console.debug(newVal, oldVal);
});
}
});


Inside this watch, I want to do some initialization when the model has a value set, but I always get "undefined", "undefined" for the newVal and oldVal. Probably I´m missing something basic, but couldn´t find anything.

Besides, calling $setViewValue doesn´t even fire the watch: maybeI misunderstood something, but I thought that $setViewValue changed the model value, and so, I expected it to fire the $watch.

Could someone explain me how is supposed all that stuff to work?? I´m clearly missing something.

Answer

If you're just looking to two-way bind data in a directive, using = in the scope and a $watch in the link function is all you need to do (watch the name of the variable on the scope):

scope.$watch('ngModel', function (/* ... */) { /* ... */ });

It might be confusing to consumers of your directives if ng-model is the name of the attribute, so I'd recommend choosing a different name (preferably that isn't prefixed with ng-).

Comments