AngularJS : How to watch service variables?

后端 未结 21 1388
盖世英雄少女心
盖世英雄少女心 2020-11-22 09:12

I have a service, say:

factory(\'aService\', [\'$rootScope\', \'$resource\', function ($rootScope, $resource) {
  var service = {
    foo: []
  };

  return          


        
相关标签:
21条回答
  • 2020-11-22 09:40

    A wee bit ugly, but I've added registration of scope variables to my service for a toggle:

    myApp.service('myService', function() {
        var self = this;
        self.value = false;
        self.c2 = function(){};
        self.callback = function(){
            self.value = !self.value; 
           self.c2();
        };
    
        self.on = function(){
            return self.value;
        };
    
        self.register = function(obj, key){ 
            self.c2 = function(){
                obj[key] = self.value; 
                obj.$apply();
            } 
        };
    
        return this;
    });
    

    And then in the controller:

    function MyCtrl($scope, myService) {
        $scope.name = 'Superhero';
        $scope.myVar = false;
        myService.register($scope, 'myVar');
    }
    
    0 讨论(0)
  • Without watches or observer callbacks (http://jsfiddle.net/zymotik/853wvv7s/):

    JavaScript:

    angular.module("Demo", [])
        .factory("DemoService", function($timeout) {
    
            function DemoService() {
                var self = this;
                self.name = "Demo Service";
    
                self.count = 0;
    
                self.counter = function(){
                    self.count++;
                    $timeout(self.counter, 1000);
                }
    
                self.addOneHundred = function(){
                    self.count+=100;
                }
    
                self.counter();
            }
    
            return new DemoService();
    
        })
        .controller("DemoController", function($scope, DemoService) {
    
            $scope.service = DemoService;
    
            $scope.minusOneHundred = function() {
                DemoService.count -= 100;
            }
    
        });
    

    HTML

    <div ng-app="Demo" ng-controller="DemoController">
        <div>
            <h4>{{service.name}}</h4>
            <p>Count: {{service.count}}</p>
        </div>
    </div>
    

    This JavaScript works as we are passing an object back from the service rather than a value. When a JavaScript object is returned from a service, Angular adds watches to all of its properties.

    Also note that I am using 'var self = this' as I need to keep a reference to the original object when the $timeout executes, otherwise 'this' will refer to the window object.

    0 讨论(0)
  • 2020-11-22 09:46

    Building on dtheodor's answer you could use something similar to the below to ensure that you don't forget to unregister the callback... Some may object to passing the $scope to a service though.

    factory('aService', function() {
      var observerCallbacks = [];
    
      /**
       * Registers a function that will be called when
       * any modifications are made.
       *
       * For convenience the callback is called immediately after registering
       * which can be prevented with `preventImmediate` param.
       *
       * Will also automatically unregister the callback upon scope destory.
       */
      this.registerObserver = function($scope, cb, preventImmediate){
        observerCallbacks.push(cb);
    
        if (preventImmediate !== true) {
          cb();
        }
    
        $scope.$on('$destroy', function () {
          observerCallbacks.remove(cb);
        });
      };
    
      function notifyObservers() {
        observerCallbacks.forEach(function (cb) {
          cb();
        });
      };
    
      this.foo = someNgResource.query().$then(function(){
        notifyObservers();
      });
    });
    

    Array.remove is an extension method which looks like this:

    /**
     * Removes the given item the current array.
     *
     * @param  {Object}  item   The item to remove.
     * @return {Boolean}        True if the item is removed.
     */
    Array.prototype.remove = function (item /*, thisp */) {
        var idx = this.indexOf(item);
    
        if (idx > -1) {
            this.splice(idx, 1);
    
            return true;
        }
        return false;
    };
    
    0 讨论(0)
提交回复
热议问题