acid
acid

Reputation: 2149

Watching changed in the service from the controller

I am trying to listen to changes in my injected service (self-updating) in the controller. In the below example you'll find two $watch cases - one that works but I don't know exactly why and one that was obvious to me, yet doesn't work. Is the second example the right way to do it? Isn't that code duplication? What is the right way to do it?

Service:

app.factory("StatsService", [
    '$timeout', 'MockDataService',
    function ($timeout, MockDataService) {
        var service, timeout;
        timeout = 5000;
        service = {
            fetch: function () {
                // Getting sample data, irrelevant, however this is what updates the data
                return this.data = MockDataService.shuffle();
            },
            grab: function () {
                this.fetch();
                return this.update();
            },
            update: function () {
                var _this = this;
                return $timeout(function () {
                    return _this.grab();
                }, timeout);
            }
        };
        service.grab();
        return service;
    }
]);

Controller:

app.controller("StatsController", [
    '$scope', 'StatsService',
    function ($scope, StatsService) {
        var chart;
        $scope.stats = StatsService;
        $scope.test = function (newValue) {
            if (arguments.length === 0) {
                return StatsService.data;
            }
            return StatsService.data = newValue;
        };

        // This doesn't work
        $scope.$watch('stats', function (stats) {
            return console.log('meh');
        });

        // This works, don't know why
        $scope.$watch('test()', function (stats) {
            return console.log('changed');
        });
    }
]);

Upvotes: 1

Views: 65

Answers (2)

luacassus
luacassus

Reputation: 6710

You could use $rootScope events. For example inside the service you could dispatch an event with $rootScope.$broadcast("somethingFetched", data) and catch it in the controller $scope.$on("somethingFetched", function(event, data) { $scope.data = data }).

More details you could find in the documentation http://docs.angularjs.org/api/ng.$rootScope.Scope

Upvotes: 0

noj
noj

Reputation: 6759

See the third parameter for $watch: objectEquality

Compare object for equality rather than for reference.

However if you're only interested in watching the returned data, then you should do:

$scope.$watch('stats.data', function (stats) {
    return console.log('meh');
});

Upvotes: 2

Related Questions