0

I've been reading that Services are great for sharing data. But I am having a hard time making all data be in sync...

For example, let's say you have

  • an ItemService with an array of items.
  • a ItemListController, which shows a list of items ($scope.items = ItemService.items)
  • a AddItemController, a form to add items to the array (using the service).

When I add a new item, it doesn't automatically shows in the list controller. My workaround so far is to use cache:false in the router so that it refreshes every time I look at it...

I can't use $scope.$apply() because the adding happens on one controller while I want to see it on another...

Nathan H
  • 48,033
  • 60
  • 165
  • 247

2 Answers2

1

You need to use $rootScope.$broadcast('item.added'); in the controller that initiates changes (AddItemController), after it successfully updates the array in the service.

Then in the ItemListController you use

$rootScope.$on('item.added', function(event){
  $scope.items = ItemService.items;
});

Check this question

Community
  • 1
  • 1
codeepic
  • 3,723
  • 7
  • 36
  • 57
  • This answer is correct but I would like some clarification on the subject. Why `$scope.items = ItemService.items` is not enough ? Why do we need to broadcast the changes ? I mean we have already set a reference to the ItemService.items object when we defined `$scope.items = ItemService.items` Shouldn't `$scope.items` be updated when we change `ItemService.items` in any other part of the application ? Isn't is what angularjs is all about "two-way data binding" ? – Sarpdoruk Tahmaz Dec 02 '15 at 16:29
  • I have to reply to your comment by posting another answer since there is 600 character limit for comments. – codeepic Dec 02 '15 at 17:14
1

@Sarpdoruk There is two-way data binding between views and controllers, but not between controllers and services. By using this line $scope.items = ItemService.items; you copy 'items' from service to items in controller but you copy by value, not by reference. You can change $scope.items in your view or controller and they will get updated between the view and controller but these changes will have no effect on the service. Same thing if you update items in the service - controller will not know that something has been changed - so you need to $broadcast or $emit that something has changed from service and listen for the changes in the controller. You can also $broadcast between controllers, directives and even services (but since services have no access to $scope, you have to use $rootScope and some people frown upon that). The bottom line is, if you really have to use a $rootScope in the service because otherwise you will have to overcomplicate parts of your app, then do it and never bother with "best practice evangelist" The first rule of the app is that it has to work, only after it works you should worry about clean code. I hope it makes it clearer now.

codeepic
  • 3,723
  • 7
  • 36
  • 57
  • Thank you for making it clearer, by the way I have found the easiest and best solution to this problem [here](http://stackoverflow.com/a/33644472/541075) As you said, `$scope.items = ItemService.items;` does not reference to the object but it copies. – Sarpdoruk Tahmaz Dec 02 '15 at 21:33