I have an idea for my AngularJS app and I'm curious if the AngularJS community would consider it okay to do it this way...
In short, I am connecting to a data API and displaying my results on the page. I have created an angular service that creates a data store on $rootScope.DataStore. I also have a service method that updates the DataStore with the data returned from an API endpoint. If I request the "products" API endpoint from inside my controller with DataStore.update('products'), this would update $rootScope.DataStore.products with my product data. Now, in the view/partial, all I need to do is say ng-repeat="product in DataStore.products" to show my data, and it doesn't matter what controller scope I am in. So, in essence my DataStore is my single source of truth.
What I feel like I gain from this method is easy to follow semantics and minimal controller coding. So, anytime the DataStore is updated, anything that's bound to DataStore also gets updated.
Would this put too much load on the $rootScope digest cycle, or is this just an odd way to do it? Or is it a totally awesome way? :) Any comments are welcome.
To appease all parties, why not just use the $cacheFactory. This allows the data request services to be stateless and basically just a getter and setter. I will admit keeping the data on the $rootScope or as a property in the service is convenient but just feels wrong. Using the $cacheFactory is pretty easy too.
First create a cache service:
Include the js file in in your app.js and then inject it into you app declaration:
Inject it in the service, use it like so:
Now all that you have to do is inject your HackerNewsService in your controller and use it by calling the methods we created on it. For example:
My experience is that using the $rootScope for storing the part of my datamodel that is common to all ngViews in my app, is the most convenient way.
is for me more readable and shorter than
with the javascript
If one uses a service or a cachefactory, every acces to the model in the html template becomes a function, which is less readable that a accessing a property of the rootScope. Using the $rootScope gives less code, and as a consequence less errors and less testing.
Of course only the common part of all ngView's is stored in $rootScope. The rest of the model is stored in the local $scope.
Watches on a function are also slower than on object properties. So performance-wise, $rootScope is also better.
This question is addressed in the AngularJS FAQ quoted here:
It seems that the team does encourage using
$rootScope
this way, with this caveat:This does not put too much load on the
$digest
cycle (which implements basic dirty checking to test for data mutation) and this is not an odd way to do things.EDIT: For more details on performance, see this answer from Misko (AngularJS dev) here on SO: How does data binding work in AngularJS? Specifically note the section on performance.
I am just facing the same issue, and it seems to me that storing it ion globally available 'location' is the right approach, but that $rootScope is not the ideal place.
I have just been researching this more, and instead of storing your data on $rootScope, you could consider using a "service" to manage your data / separate concerns, 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" you create using that approach, whether you save the data in memory, cacheFactory, localstorage (as alluded to here), and/or to your DB (eg. via AJAX), is up to whatever suits the needs of your app. It also means changes to how you store your data can be made independently, as required.
I guess I'm not sure why you need to use the rootScope? The lifetime of a service instance is the entire application as well, so whatever data schema / semantics you are using could also be stashed right in the service itself and it would be shared across controllers. Either of those methods however don't survive refresh like using local storage would.
The rest of it sounds like a lazy loading approach. Where the service is the only thing "aware" of whether the data has been loaded from the remote and returns it if it is already cached and caches and returns it if its not? If I understand that part correctly its a good pattern.
edit: Here I am taking a similar approach to the lazy loading, notice the cache is just in the service itself: