Is it possible to set up a $watch
on an array of objects inside a service (I\'d like the $watch
declaration itself to be inside the service)?
Can you clarify what you want to achieve? As I understand, you are getting an array of objects from the server as your model. Then it's not clear:
In case 1, you don't really need to use $watch (or rather $watchCollection) but you should iterate through the array you received from the server and verify the changes (the same what $watchColleciton would do). In case the object is different to the one you currently hold - you call object.$save() on this element.
In case 2, use $watchCollection() on the $scope passed as a parameter to your service function or use $rootScope if you hold your array in the $rootScope.
I can provide you with real code if you would clarify the scenarios.
services by their very nature are like classes and house methods. You can set up a method which you call from your controller who's argument is the scope and applies a watch expression:
app.service('myservice',function(){
this.listen = function($scope) {
$scope.$watch(function(){return someScopeValue},function(){
//$scope.dosomestuff();
});
}
});
//your controller
function myCtrl($scope,myservice) {
$scope.listen = function() {
myservice.listen($scope);
}
//call your method
$scope.listen();
}
update: If you are trying to watch a private local variable inside of a service, see the accepted answer using $rootScope. If you are trying to $watch a $scope variable within a local scope than the above is your best bet. They are achieving two very different things.
You can add any expression to the set of watches by injecting the $rootScope
and using a function a first argument to the $watch
method. Pseudo-code:
$rootScope.$watch(function() {
return //value to be watched;
}, function watchCallback(newValue, oldValue) {
//react on value change here
});
Don't forget about the third, Boolean argument to the $watch
method. You need to specify true
if you want to deep-watch an entire object for changes.
Hey just had a situation where I had a pretty big watch setup on 2 different controllers.
As I didn't want to duplicate any code I just defined to function in my service :
angular
.module('invoice')
.factory('invoiceState', function () {
var invoice = {
client_info: {
lastname: "",
firstname: "",
email: "",
phone: "",
id_client: "",
...
}
}
invoice.watchAccommodation = function (newVal, oldVal) {
var accommodation = newVal;
//Whatever you would normally have in your watch function
}
Then I can just call this function in the watch of any controller into which I injected the service
function NewInvoiceCtrl(invoiceState) {
$scope.$watch('invoice.accommodation',invoiceState.watchAccommodation, true);
}
I do not have much experience with AngularJS so I can't really go into the performance aspects of this approach but it works ;)