3

I have 2 controllers: one for menu(dynamic list of elements we can add/remove) and one for ng-view.

I need to access menu elements from ng-view controller. So, as I understand it right, I should create service so menu objects will be available in any controller, I need just to inject it.

Done.

But!

I need these objects in rendering. So, I should put menu elements in scope of both controllers? That's ugly: I should update it's value each time I update elements in service. Damn.

So, currently it works with rootScope and service, which has method to deal with elements list update/add/remove AJAX. But I think something is wrong here.

Any advices?

dt0xff
  • 1,553
  • 1
  • 10
  • 18
  • You could use an Angular 'value' and inject that into both. I have also just assigned a service to a scope property and referenced a property of the service directly in my template. (e.g {{$scope.myService.someProperty}}) – Craig Squire Feb 19 '14 at 19:27
  • @CraigSquire, I'm not sure is it good idea to assign service into $scope, because it will be fully checked in AngularJS $digest loop. I don't need that. But value... it is good, but damn... why not rootScope? So we should create app.value for each service(e.g. similar situation)? – dt0xff Feb 19 '14 at 19:47
  • Sure, maybe just watch a property of the service which references an object. $scope.myData = $scope.myService.myData and reference $scope.myData.someProperty in your template. Not sure what you mean by app.value for each service. It is also acceptable to store data on $rootScope, yes. I typically don't do that because it can become a dumping ground when you don't know where else to put something. – Craig Squire Feb 19 '14 at 19:57
  • Could you share some code in plunker? Might not need a service but shouldn't use global scope as it breaks encapsulation. – sidhuko Feb 19 '14 at 20:25
  • http://plnkr.co/edit/yLjqgJCdjwUf3WSg1P4Y?p=preview – dt0xff Feb 25 '14 at 00:35
  • @CraigSquire I wonder, can I use function instead of object? So it will check for reference, returned in function... For value per service I mean cases, when I have few services and I wanna use it's data to display some things. – dt0xff Feb 25 '14 at 00:38

1 Answers1

3

If all you have is data then you can use a Value. Inject the Value into each of your controllers and store it on your scope, then reference a property of the Value in your template. If you use a Service, you can do pretty much the exact same thing. My example shows one solution using each.

See this example: http://plnkr.co/edit/qTbSjnf6Q2FVDurGZhKd

<div ng-controller="MainCtrl">
  <input ng-model="mainVal.value"></input>
  <input ng-model="mainSvcVal.value"></input>
</div>
<div ng-controller="OtherCtrl">
  <input ng-model="otherVal.value"></input>
  <input ng-model="otherSvcVal.value"></input>
</div>

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

app.value('MyValue', {value: "Hello There"});

app.service('MyService', function() {
  this.myData = {
    value: "Goodbye"
  }
});

app.controller('MainCtrl', function($scope, MyValue, MyService) {
  $scope.mainVal = MyValue;
  $scope.mainSvcVal = MyService.myData;
});

app.controller('OtherCtrl', function($scope, MyValue, MyService) {
  $scope.otherVal = MyValue;
  $scope.otherSvcVal = MyService.myData;
});

One thing to note would be if you reassign MyService.myData to a new object, it would break the relationship.

Craig Squire
  • 2,141
  • 14
  • 13
  • It looks good, but I'm not sure. So, if we need to create service, we should create app.value to store it's data too? Why not just service? So what's a purpose of service? – dt0xff Feb 19 '14 at 19:49
  • A 'value' is just a service that you can assign a primitive, existing object or function to, instead of using a factory or constructor function as you do when you create a 'service'. A 'service' can also store data. http://docs.angularjs.org/api/auto/object/$provide – Craig Squire Feb 19 '14 at 20:11
  • I found a similar question with other ways as well. http://stackoverflow.com/questions/12576798/angularjs-how-to-watch-service-variables – Craig Squire Feb 19 '14 at 20:22
  • I can't use idea with service data reference. Because it will be replaced with new object each time. Can I use function to get it? – dt0xff Feb 25 '14 at 00:39
  • Use a $watch on the service property. – Craig Squire Feb 25 '14 at 01:35
  • But what if I have more than one property? Data, page, total, sort, selected counter, etc. Will it be huge overhead? – dt0xff Feb 25 '14 at 12:54
  • Are all of your properties in one object? There are 3 kinds of 'watch'. $watch (not deep) just watches for the object reference to change, $watch (deep) watches for anything in that object to change or $watchCollection is in between and will watch for the object reference or the top level properties to change. One of those should work. Unless you use a lot of deep watches on your page, there won't be any performance problems. Can you update your plunker with an example of "real data" with all those properties you list? – Craig Squire Feb 25 '14 at 14:05
  • Check out this blog post and try his github demo. http://www.bennadel.com/blog/2566-Scope-watch-vs-watchCollection-In-AngularJS.htm – Craig Squire Feb 25 '14 at 14:08
  • wow! Thank you so much. It looks really good. But one question: what is about default angular bindings? It uses $watch(true) way, $watchCollection or $watch() way? Just curious. – dt0xff Feb 25 '14 at 14:20