简体   繁体   中英

angular watch object not in scope

I have a service in which values can change from outside Angular:

angularApp.service('WebSocketService', function() {
    var serviceAlarms = [];
    var iteration = 0;

    this.renderMessages = function(alarms, socket) {
        if (! angular.equals(serviceAlarms, alarms)) {
            serviceAlarms = alarms;
            iteration++;
        }
    };

    this.getAlarms = function () {
        return serviceAlarms;
    };
    this.iteration = function () {
        return iteration;
    };
    this.socket = initSocketIO(this);
});

The initSocketIO function makes callbacks to this services renderMessages() function and serviceAlarms variable gets changed on a steady basis.

Now i am trying to watch for changes in this service like so:

controllers.controller('overviewController', ['$scope', 'WebSocketService', function ($scope, WebSocketService) {
    $scope.$watch(
        function () {
             return WebSocketService.iteration();
        },
        function(newValue, oldValue) {
            $scope.alarms = WebSocketService.getAlarms();
        },
        true
    );
}]);

to no avail. The second function provided to $watch never gets executed except on controller initialization.

I have tried with and without true as third parameter.

I ended up using the solution below since $watch didn't work as excpected.

I refactored the solution to use $rootScope in combination with:

angularApp.run(['$rootScope', function($rootScope){
    $rootScope.socket = {};
    $rootScope.socket.alarms = [];
    $rootScope.socket.faults = [];
    $rootScope.socket.renderErrors = function(faults, socket) {
        var faultArray = [];
        angular.forEach(faults, function(error) {
            error.value ? faultArray.push(error) : null;
        });
        if (! angular.equals($rootScope.socket.faults, faultArray)) {
            $rootScope.socket.faults = faultArray;
            $rootScope.apply();
        }
    };

    $rootScope.socket.renderMessages = function(alarms, socket) {
        if (! angular.equals($rootScope.socket.alarms, alarms)) {
            $rootScope.socket.alarms = alarms;
            $rootScope.$apply();
        }
    };

    $rootScope.socket.socket = initSocketIO($rootScope.socket);
}]);

Now i have my socket-updated-model in all scopes to use freely in controllers and views. Controller example:

$scope.acknowledgeAlarm = function(alarm) {
    $scope.socket.socket.emit('acknowledgeAlarm', {
        hash:alarm.icon.hash,
        id:alarm.id
    });
};

View example:

<div ng-repeat="alarm in socket.alarms">
    {{alarm.name}} {{alarm.icon.progress}}
</div>

您应该使用$rootScope.$watch (而不是$scope.$watch

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM