I have a watch setup against the model of a ui-select2 dropdown (from ui-bootstrap). The watch fires on load but not on data changes and I can't figure out why.
It isn't the usual problem of not $apply'ing the model change or not using the third parameter for equality comparison (at least from my code).
What do I need to do to get it to fire?
Here is a plunk demonstrating the issue.
Try passing true
as a 3rd argument to .$watch()
$rootScope.Scope
documentation
$watch(watchExpression, listener, objectEquality)
objectEquality(optional) – {boolean=} – Compare object for equality rather than for reference.
I fixed some stuff.
http://plnkr.co/edit/5Zaln7QT2gETVcGiMdoW?p=preview
The JS
var myMod = angular.module("myApp",[]).controller("MainController", function($scope){
$scope.myModel = {selectedId:null};
}).controller("DetailController",function($scope){
$scope.items = [1,2,3,4];
$scope.watchHitCount = 0;
$scope.$watch('myModel.selectedId', function(newVal, oldVal){
console.log(newVal + " " + oldVal);
$scope.watchHitCount++;
},true);
});
The index.html
<body ng-app="myApp">
<div ng-controller="MainController">
<ng-include src="'detail.html'" ng-controller="DetailController"></ng-include>
</div>
</body>
The detail.html
<pre>watch hit: {{watchHitCount}}</pre>
<pre>selected value: {{myModel.selectedId}}</pre>
<select ng-model="myModel.selectedId" ui-select2="">
<option></option>
<option ng-repeat="item in items" value="{{item}}">{{item}}</option>
</select>
It was complaining about not finding the controller so I set it up the way I normally would with a named ng-app and a module declared that has controllers defined on it.
I also added an object to hold the value in your model. It is bad practice to use the $scope object as your model, instead your scope should refer to an object that is your model.
There are a simple fix for that, to use watch with complex object instead of simple variable
For example (DON"T USE)
$scope.selectedType=1;//default
$scope.$watch(
function () {
return $scope.selectedType;
},
function (newValue, oldValue) {
if (!angular.equals(oldValue, newValue)) {
$scope.DoWork();
}
},
true);
But Use below
$scope.selecteditem={selectedType:1};
$scope.$watch(
function () {
return $scope.selecteditem.selectedType;
},
function (newValue, oldValue) {
if (!angular.equals(oldValue, newValue)) {
$scope.DoWork();
}
},
true);
note that "slectedTypes" in the second example located inside object, not just scope variable. this will work even in old Angular versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With