Reputation: 9759
I have a controller in my Angular app:
(function (angular) {
function MyController() {
this.name = 'Dave';
// I want to have code like this:
/*
$scope.$watch('name', function (newValue, oldValue) {
console.log(oldValue, "changed to", newValue);
});
*/
}
window.myApp = angular.module('myApp', [])
.controller('MyController', [MyController]);
})(angular);
Is there a way to use the features of $scope.$watch
when attaching values to the MyController
prototype?
I did notice that in my code, if I add something like ng-controller="MyController as myCtrl"
, and change my $scope.$watch
statement to $scope.$watch('myCtrl.name', ...)
, it'll work after I add the $scope
dependency, but that feels like tying my controller to my views, which feels wrong.
Edit
To attempt to clarify on what I'm asking. My HTML is something like this:
<div ng-app="myApp">
<div ng-controller="MyController as myCtrl">
<input type="text" ng-model="myCtrl.name" />
<p>{{myCtrl.helloMessage}}</p>
</div>
</div>
My controller is something like this:
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
this.name = 'World';
this.helloMessage = "Hello, " + this.name;
var self = this;
$scope.$watch('myCtrl.name', function () {
self.helloMessage = "Hello, " + self.name;
});
}]);
That currently works, but as you can see, in the $watch
call, I have to reference my controller by the controllerAs
name from my view, which is less than ideal.
I've setup an example on Plunkr
Upvotes: 5
Views: 3643
Reputation: 7438
Expression that is evaluated on each $digest cycle. A change in the return value triggers a call to the listener. Watch expression can be a sting or function.
- string: Evaluated as expression
- function(scope): called with current scope as a parameter.
angular.module('app', []).controller('MainCtrl', function($scope) {
this.name = 'World'
this.helloMsg = ''
$scope.$watch(function() {
return this.name
}.bind(this), function(newName) {
this.helloMsg = "Hello, " + newName
}.bind(this))
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app'>
<div ng-controller='MainCtrl as ctrl'>
<input type='text' ng-model='ctrl.name' />
{{ ctrl.helloMsg }}
</div>
</div>
Upvotes: 4
Reputation: 22323
You can avoid being bound to the view by using angular.bind
in your watch, i.e.
$scope.$watch(angular.bind(this, function () {
self.helloMessage = "Hello, " + self.name;
}));
https://docs.angularjs.org/api/ng/function/angular.bind
Upvotes: 3
Reputation: 4278
I might be wrong but I believe the $scope is automatically injected by angular.
Here's an example of a controller being declared:
var myApp = angular.module('myApp',[]);
myApp.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
Notice how $scope dependency is declared '$scope'
and injected function($scope)
In other words, should yours look something like this ?
function MyController($scope) {}
window.myApp = angular.module('myApp', [])
.controller('MyController', ['$scope', MyController($scope)]);
EDIT:
I understand now. I've never had a need to use "controller as" but why not do it like this ?
<div ng-app="myApp">
<div ng-controller="MyController">
<input type="text" ng-model="name" />
<p>{{helloMessage}}</p>
</div>
</div>
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
this.name = 'World';
this.helloMessage = "Hello, " + this.name;
var self = this;
$scope.$watch('name', function () {
self.helloMessage = "Hello, " + self.name;
});
}])
Upvotes: 0