I have this small sample in which I hoped to see log messages in browser console indicating $scope watcher is working well, but it's unfortunately not the case.
<!doctype html>
<html ng-app="demo">
<head>
<script src="bower_components/angular/angular.js"></script>
<script>
var app = angular.module('demo', ['ng']);
app.controller('demoCtrl', function($scope) {
var self = this;
self.searchText = '';
$scope.$watch('self.searchText', function(n, p) {
console.log('searchText changed from', n, 'to', p);
});
});
</script>
</head>
<body ng-controller="demoCtrl as ctrl">
<input type="text" ng-model="ctrl.searchText" />
</body>
</html>
You need to use the alias ctrl
(not self
) in $scope.$watch(...)
:
<!doctype html>
<html ng-app="demo">
<head>
<script src="bower_components/angular/angular.js"></script>
<script>
var app = angular.module('demo', ['ng']);
app.controller('demoCtrl', function($scope) {
var self = this;
self.searchText = '';
$scope.$watch('ctrl.searchText', function(n, p) {
console.log('searchText changed from', n, 'to', p);
});
});
</script>
</head>
<body ng-controller="demoCtrl as ctrl">
<input type="text" ng-model="ctrl.searchText" />
</body>
</html>
When ng-controller="demoCtrl as ctrl"
is used, Angular creates a link to the controller context object this
into the scope: $scope.ctrl
.
Change your $watch
to:
$scope.$watch(function() {
return self.searchText;
}, function(n, p) {
console.log('searchText changed from', n, 'to', p);
});
In form you used $scope.$watch
watching expression should be part of scope or root scope.
So you should change your code like this:
<!doctype html>
<html ng-app="demo">
<head>
<script src="bower_components/angular/angular.js"></script>
<script>
var app = angular.module('demo', ['ng']);
app.controller('demoCtrl', function($scope) {
var self = this;
$scope.searchText = '';
$scope.$watch('searchText', function(n, p) {
console.log('searchText changed from', n, 'to', p);
});
});
</script>
</head>
<body ng-controller="demoCtrl as ctrl">
<input type="text" ng-model="searchText" />
</body>
</html>
or use another form and change you code like this:
<head>
<script src="bower_components/angular/angular.js"></script>
<script>
var app = angular.module('demo', ['ng']);
app.controller('demoCtrl', function($scope) {
var self = this;
self.searchText = '';
$scope.$watch(function() { return self.searchText; }, function(n, p) {
console.log('searchText changed from', n, 'to', p);
});
});
</script>
</head>
<body ng-controller="demoCtrl as ctrl">
<input type="text" ng-model="ctrl.searchText" />
</body>
</html>
The answer is simple -
Angular watches the expression on the scope variable and not on the controller instance.
To make the code work you need to do modify the controller code as following
var self = this;
self.searchText = '';
$scope.self = this;
$scope.$watch('self.searchText', function(n, p) {
console.log('searchText changed from', n, 'to', p);
});