AngularJS using $ rootScope as a data store

I have an idea for my AngularJS application, and I'm curious if the AngularJS community will consider this normally to do it this way ...

In short, I connect to the data API and display the results on the page. I created an angular service that creates a data warehouse in $ rootScope.DataStore. I also have a service method that updates a DataStore with data returned from the API endpoint. If I request the endpoint of the “products” API from my controller using DataStore.update (“products”), this will update the $ rootScope.DataStore.products data with my product data. Now, in the view / partial, all I have to do is say ng-repeat = "product in DataStore.products" to show my data, and it doesn't matter which area of ​​the controller I am in. So essentially my DataStore is my only source of truth.

I feel that getting from this method is easy to follow semantics and minimal coding of the controller. Thus, at any time when the DataStore is updated, everything related to the DataStore is also updated.

Will it load too much into the digest $ rootScope loop, or is it just a weird way to do this? Or is it awesome? :) Any comments are welcome.

+57
angularjs
May 24 '13 at 15:58
source share
5 answers

This question is covered in AngularJS Frequently Asked Questions :

Sometimes there are pieces of data that you want to make the entire application global. To do this, you can enter $ rootScope and set values ​​to it, like any other area. Since areas inherited from the root area, these values ​​will be accessible to the expressions attached to the directives, such as ng-show, just like the values ​​in the local $ scope.

The command seems to encourage the use of $rootScope in this way, with this warning:

Of course, the global state sucks, and you should use $ rootScope sparingly, as you would (hopefully) use global variables in any language. In particular, do not use it for code, but only data. If you are tempted to put a function on $ rootScope, it is almost always better to put it in services that can be entered where necessary, and more easily tested.

Conversely, do not create a service whose sole purpose is to store and return a bit of data.

This doesn't load the $digest loop too much (which implements a basic dirty check to check for data mutations), and it's not a weird way to do something.

EDIT: For more on efficiency, see this answer from Misko (AngularJS dev) here on SO: How does data binding work in AngularJS? Check out the performance section.

+88
May 24 '13 at 16:11
source share

To reassure all parties, why not just use $ cacheFactory. This allows the data request services to be stateless and basically just the recipient and installer. I admit that storing data on $ rootScope or as a property in the service is convenient, but just feels wrong. Using $ cacheFactory is pretty simple.

First create a cache service:

 angular.module('CacheService', ['ng']) .factory('CacheService', function($cacheFactory) { return $cacheFactory('CacheService'); }); 

Include the js file in your app.js and then enter it in the application declaration:

 var MyApp = angular.module('MyApp', ['CacheService']); 

Add it to the service, use it like this:

 'use strict' MyApp.factory('HackerNewsService', function(CacheService) { return { getNews: function(key) { var news = CacheService.get(key); if(news) { return news; } return null; }, setNews: function(key, value) { CacheService.put(key, value); }, clearNews: function(key) { CacheService.put(key, ''); } }; }); 

Now all you have to do is enter the HackerNewsService into your controller and use it by calling the methods we created on it. For example:

 HackerNewsService.setNews('myArticle', {headline: 'My Article', body: 'This is the body'}); $scope.article = HackerNewsService.getNews('myArticle'); 
+32
Oct 01 '13 at 15:10
source share

My experience is that using $ rootScope to store the part of my datamodel that is common to all ngViews in my application is the most convenient way.

 <div>{{mymodel.property}}</div> 

more readable and shorter for me

 <div>{{getPropertyModel()}}</div> 

with javascript

 app.factory('MyModel', function(){ return { getModel: function() { ... }, setModel: function(m) { ... }, } }); app.controller('ctrl', ['$scope', 'MyModel', function($scope, MyModel){ $scope.getPropertModel = function() { return MyModel.getModel().property; }; }]); 

If you use a service or cashew, each access to the model in the html template becomes a function that is less readable to access the rootScope property. Using $ rootScope gives less code and, as a result, fewer errors and less testing.

Of course, only the general part of all ngView is stored in $ rootScope. The rest of the model is stored in the local area $.

Hours on functions are also slower than on properties of an object. Thus, it is better to work with $ rootScope.

+8
Nov 18 '13 at 14:57
source share

I think I'm not sure why you need to use rootScope? The lifetime of the service instance is also the whole application, so any data schema / semantics that you use can also be hidden right in the service itself, and it will be available to all controllers. However, any of these methods does not withstand updates, like using local storage.

The rest sounds like a lazy approach to downloading. Where is the service the only thing “informed” about whether data has been downloaded from the remote and whether it returns if it is already cached and cached and returns if it is not? If I understand this part correctly, this is a good example.

edit: Here I take a similar approach to lazy loading, notice that the cache is only in the service itself:

 angular.module('HN_Reddit_Mashup.Services', []) .factory('HackerNews', function($http) { var HackerNewsCache = {}; return { get: function(url) { return HackerNewsCache[url] || (HackerNewsCache[url] = $http.jsonp("http://api.thriftdb.com/api.hnsearch.com/items/_search?q=" + url + "&callback=JSON_CALLBACK")); }, }; }) 
0
May 24 '13 at 16:11
source share

I just run into the same problem, and it seems to me that keeping its globally accessible “location” is the right approach, but this $ rootScope is not an ideal place.

I just explored this more, and instead of storing your data in $ rootScope, you might consider using a “service” to manage your data / individual issues, as described here (especially the last code example): http: // joelhooks .com / blog / 2013/04/24 / modeling-data-and-state-in-your-angularjs-application /

Then, in the “service” that you create using this approach, whether you save the data in memory, cacheFactory, localstorage (as indicated here ) and / or in your database (for example, via AJAX), depends on the needs of your application. It also means that changes to the way you store your data can be made independently, as needed.

0
Oct 11 '13 at 3:19
source share



All Articles