Reputation: 3508
I created a service which basically creates an interval, which will eventually do a $http post to a webapi to retrieve messages. Right now I'm just adding a new message object to an array for testing.
On the controller side I initialize the service and place a watch on one of the service properties, idea being when the service adds a new message I'll watch to display the notification to the user. Obviously this won't add a new message to the displayedNotifications array on EVERY call, but again this is just testing a prototyping.
The following is my service.
(function () {
'use strict';
var serviceId = "notificationService";
//angular.module('app').factory(serviceId, ['helpersService', '$interval', function (helpersService, $interval) {
angular.module('app').factory(serviceId, ['helpersService', '$interval', function (helpersService, $interval) {
var defaultOptions = {
url: undefined,
interval: 1000
};
var myIntervalPromise = undefined;
var displayedNotifications = [];
//function onNotificationSuccess(response) {
// alert("in success");
// return response.data;
//}
//function onNotificationFailed(response) {
// alert("in Failure");
// throw response.data || 'An error occurred while attempting to process request';
//}
function initializeNotificationService(configOptions) {
var passedOptions = $.extend({}, defaultOptions, configOptions);
if (passedOptions.url) {
myIntervalPromise = $interval(
function() {
console.log(passedOptions.url);
// eventually this push will accept a string/object returned from a webapi call
displayedNotifications.push({ messageobject: "this is new message" });
}, passedOptions.interval);
//alert("in initializeNotificationService");
return myIntervalPromise;
}
return myIntervalPromise;
}
//$scope.$on('$destroy', function() {
// if (angular.isDefined(myIntervalPromise)) {
// $interval.cancel(myIntervalPromise);
// myIntervalPromise = undefined;
// }
//});
return {
// methods
initializeNotificationService: initializeNotificationService,
//properties
displayedNotifications : displayedNotifications
};
}]);
})();
The following is my controller
(function () {
'use strict';
var controllerId = 'MessageCtrl';
angular.module('app').controller(controllerId, ['notificationService', '$scope',
function (notificationService, $scope) {
var vm = this;
//vm.notifications = [];
vm.initialize = function () {
// initialize tyhe notification service here
notificationService.initializeNotificationService({url:'this is a test url', interval: 5000})
.then(
function (response) {
vm.notifications.push(response);
alert("successful call");
},
function(response) {
alert("failure to call");
},
function(iteration) {
// **a break point here clearly shows this property being changed**
console.log(notificationService.displayedNotifications);
//NEW EDIT HERE
$scope.notifications = notificationService.displayedNotifications;
}
);
$scope.$watch('notifications ', function (newValues, oldValues) {
alert("watcher notified that notifications have changed");
}, true);
};
vm.alertClicked = function (alert) {
alert.status = 'old';
};
// call to init the notification service here so when the controller is loaded the service is initialized
vm.initialize();
}]);
})();
I would expect that every 5 seconds when a new message object is added to the services displayedNotifications property that the alert in the watch function would fire. However it only fires ones when everything is initialized then it doesn't again. What am I doing wrong?
NEW EDIT
Changed the notifcation function of the '.then' in the controller to assign the value of displayNotifications
to set $scope.notifications
and set the watch to that variable and that worked. But that being said it seems bad to set a variable at the $scope level... is there a way to watch a variable on the controller such as the commented out line of vm.notifications =[];
???
Upvotes: 0
Views: 137
Reputation: 26828
notificationService.displayedNotifications
is not on the scope. You call **$scope**.$watch
after all.
You can add either the service or just the property to the scope:
$scope.displayedNotifications = notificationService.displayedNotifications;
$scope.watch('displayedNotifications', ...
In your case there is no notificationService.displayedNotifications
on the scope, so it can't change. That's why the function runs only once.
Another alternative is using a function as watch expression:
$scope.$watch(function() {
return notificationService.displayedNotifications.length;
}, function (newValues, oldValues) {
Angular checks if the return value of the function has changed.
As @ShawnC. mentioned you can also use events. In your service you send one via $rootScope.$broadcast
and in your controller you receive it with $scope.$on
(I wouldn't use $rootScope
in the controller).
The last alternative I can think of is handle it in your callbacks. They are called anyway so a watch is kind of an overhead.
Upvotes: 1