Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS using $rootScope as a data store

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 AngularJS 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.

like image 559
Chris Collins Avatar asked May 24 '13 15:05

Chris Collins


People also ask

What is $rootScope in AngularJS?

All applications have a $rootScope which is the scope created on the HTML element that contains the ng-app directive. The rootScope is available in the entire application. If a variable has the same name in both the current scope and in the rootScope, the application uses the one in the current scope.

How many $rootScope an AngularJS application can have?

The scope in AngularJS is hierarchical in nature: The $rootScope acts as a global variable. All the $scopes of an AngularJS application are children of the $rootscope. An app can have only one $rootScope.

What is difference between $scope and $rootScope object?

The main difference is the availability of the property assigned with the object. A property assigned with $scope cannot be used outside the controller in which it is defined whereas a property assigned with $rootScope can be used anywhere.


2 Answers

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:

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

Include the js file in in your app.js and then inject it into you app declaration:

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

Inject it in the service, use it like so:

'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 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:

HackerNewsService.setNews('myArticle', {headline: 'My Article', body: 'This is the body'}); $scope.article = HackerNewsService.getNews('myArticle'); 
like image 26
Jordan Papaleo Avatar answered Oct 04 '22 02:10

Jordan Papaleo


This question is addressed in the AngularJS FAQ quoted here:

Occasionally there are pieces of data that you want to make global to the whole app. For these, you can inject $rootScope and set values on it like any other scope. Since the scopes inherit from the root scope, these values will be available to the expressions attached to directives like ng-show just like values on your local $scope.

It seems that the team does encourage using $rootScope this way, with this caveat:

Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. If you're tempted to put a function on $rootScope, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.

Conversely, don't create a service whose only purpose in life is to store and return bits of data.

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.

like image 96
Dan Avatar answered Oct 04 '22 04:10

Dan