Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / CSS3

AngularJS Data Sharing Controller to Controller to Service to API

4.83/5 (4 votes)
3 Mar 2016CPOL1 min read 18.2K  
Getting it all together - Controller, Service, $http, caching and more

Background

A common issue that people discuss is about data sharing, how should we get data from some server API to an angular controller and then share this data with other controllers.

Do Not Use $http Directly

Some people like to use $http in the controller to directly call their server side API.

JavaScript
function DisplayDataController($http) {
 $http.get(configuration.consts.baseApiUrl + 'ServerUrl/GetSomeValue', {id: id}).then(function (data) {

 });
}

This is bad practice for a few reasons:

  • The controller should handle display logic only.
  • If you want to change the call and reuse it in different places, you need to change it in all locations.
  • Each controller stores its own data and may potentially cost in multiple calls that can be minimized to one.

Using AngularJS Service

First, let's start to encapsulate under a single facade all of the outgoing API calls, for this, we will create an angularJS service. A service in angular is very useful especially considering the fact that it's actually a singleton, we will use this to our advantage later on.

JavaScript
MyModule.service('DataService', function ($http) {
   this.GetSomeData = function(id) {
      return $http.get(configuration.consts.baseApiUrl + 'ServerUrl/GetSomeData', {id: id});
   };
});

MyModule.controller('DisplayDataController', function (DataService) {
   DataService.GetSomeData(id).then(function (data) {
       // Use the data
   });
});

Note: Read the following article in order to understand how to skip using data.data (the http response object) and simply access the actual data from the server: http://www.codeproject.com/Articles/1078528/AngularJS-Loader-and-Error-Handling-Infrastructure

What we have done is create a service which calls $http. Now the controller uses the service and not directly the $http.

But if a different controller will use this service, it will call the server again, sure we can set cache: true, but this is a simple example, what will happen in a highly complex system?

Final Solution, Service With Caching Mechanism

Now let's add some caching logic for the complete solution:

JavaScript
MyModule.service('DataService', function ($http, $q) {
        var cache = {};
        return {
            get: function(id) {
                var deferred = $q.defer();

                if (cache[id] != null) {
                        deferred.resolve(cache[id]);
                    } else {
                        $http.get(configuration.consts.baseApiUrl + 
			'ServerUrl/GetSomeData', {id: id}).then(function(data) {
                            cache[id] = data.data[0];
                            deferred.resolve(data.data[0]);
                        });
                    }

                return deferred.promise;
            }
        };
    });

So what we've accomplished here is a service with a cache, now we can call our "DataService" from different controllers and share the same logic and data.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)