$watch inside a service?

AngularjsAngularjs Service

Angularjs Problem Overview


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)?

Angularjs Solutions


Solution 1 - Angularjs

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.

Solution 2 - Angularjs

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.

Solution 3 - Angularjs

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:

  1. Do you want to verify if some objects in the array have been changed (maybe since the last call to the server in case you do recurrent pooling)?
  2. Do you want to verify if some objects in the array have been changed by the user via some front-end control elements?

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.

Solution 4 - Angularjs

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 ;)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKuba OrlikView Question on Stackoverflow
Solution 1 - Angularjspkozlowski.opensourceView Answer on Stackoverflow
Solution 2 - Angularjsbtm1View Answer on Stackoverflow
Solution 3 - AngularjsAlexander BurakevychView Answer on Stackoverflow
Solution 4 - AngularjsDennis de BestView Answer on Stackoverflow