0

I have a service for storing some application common data. This service can also modify this data and react to events. However I am having trouble with propagating the changes to controllers that are using this service.

I've seen this question and this question, but the solutions don't work for me.

I created a plunker that shows what is my core problem. There is a service object storing common data in sharedObject. It has a function updateObject, which can update the data (in my real app it sends a request to a server). The service is used by main controller. However, when updateObject is called in the service, data are not updated in the controller.

Why is that? Also is this a best practice or am I doing somethign wrong?

Here's the code:

app = angular.module('app', []);

app.factory('object', ['$timeout', function($timeout){
  var sharedObject = {attr1: '', attr2: ''};
  var updateObject = function() {
    $timeout(function(){
      sharedObject = {attr1: 'new value', attr2: 'update value'};
      console.log('updated');
    }, 1000);
  }
  updateObject();
  return sharedObject;
}]);

app.controller('main', [
  '$scope', 'object', function($scope, object) {
    $scope.$watch(function(){return object}, function(obj){
      console.log(obj);
      $scope.object1 = obj;
      }, true);
  }
]);
Community
  • 1
  • 1
davekr
  • 2,266
  • 1
  • 26
  • 32

2 Answers2

1

The problem is that the timeout callback doesn't update the object you're watching. It replaces it by another object. So the watcher still sees the old object, unmodified.

Replace the code, as in this updated plunker, by

sharedObject.attr1 ='new value';
sharedObject.attr2 = 'update value';

and you'll see the values change in the page.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks! However is there a way to do this in one assigment? Eg. if I had dozen of attributes on this object, I wouldn't want to write this line for every attribute. – davekr Jul 14 '13 at 12:27
  • 1
    Wrap the actual object (`sharedObject`), with the dozen fields into another one (`watched`) containing this object as unique attribute. Never replace `watched`, but assign another object to `watched.sharedObject`. – JB Nizet Jul 14 '13 at 12:30
1

The problem is that you are replacing the object that sharedObject points initially with another object altogether in update method. You controller would be still holding the reference to the older object.

What you need to do is update the sharedObject in place. See my updated plunkr

Basically you need to do something like this in update method

 sharedObject.attr1= 'new value';
 sharedObject.attr2= 'update value';
Chandermani
  • 42,589
  • 12
  • 85
  • 88