Convert Angular HTTP.get function to a service

angularjs, service

Solution

Think in terms of modules and dependency injection.

So, lets say you have these three files

<script src="controllers.js"></script>
<script src="services.js"></script>
<script src="app.js"></script>

You would need three modules

1. Main App Module

angular.module('MyApp', ['controllers', 'services'])
  .config(['$routeProvider', function($routeProvider){
    $routeProvider
      .when('/bookslist', {
        templateUrl: 'partials/bookslist.html', 
        controller:  "BooksListCtrl"
      })
      .otherwise({redirectTo: '/bookslist'});
  }]);

Notice that the other two modules are injected into the main module, so their components are available to the whole app.

2. Controllers Module

Currently your controller is a global function, you might want to add it into a controllers module

angular.module('controllers',[])
  .controller('BooksListCtrl', ['$scope', 'Books', function($scope, Books){
    Books.get(function(data){
      $scope.books = data;
    });

    $scope.orderProp = 'author';
  }]);

`Books` is passed to the controller function and is made available by the services module which was injected in the main app module.

3. Services Module

This is where you define your `Books` service.

angular.module('services', [])
  .factory('Books', ['$http', function($http){
    return{
      get: function(callback){
          $http.get('books.json').success(function(data) {
          // prepare data here
          callback(data);
        });
      }
    };
  }]);

There are multiple ways of registering services.

- service: is passed a constructor function (we can call it a class) and returns an instance of the class.

- provider: the most flexible and configurable since it gives you access to functions the injector calls when instantiating the service

- factory: is passed a function the injector invokes when instantiating the service.

My preference in using the `factory` function and just have it return an object. In the example above we just return an object with a `get` function that is passed a success callback. You could change it to pass an error function too.

Edit Answering @yair's request in the comments, here's how you would inject a service into a directive.

4. Directives Module

I follow the usual pattern, first add the js file

<script src="directives.js"></script>

Then define a new module and register stuff, in this case a directive

angular.module('directives',[])
  .directive('dir', ['Books', function(Books){
    return{
      restrict: 'E',
      template: "dir directive, service: {{name}}",
      link:function(scope, element, attrs){
        scope.name = Books.name;
      }
    };
  }]);

Inject the directive module to the main module in `app.js`.

angular.module('MyApp', ['controllers', 'services', 'directives']) 

You might want to follow a different strategy and inject a module into the directives module

Notice that the syntax inline dependency annotation is the same for almost everything. The directive is injected the same Books service.

Updated Plunker: http://plnkr.co/edit/mveUM6YJNKIQTbIpJHco?p=preview

Problem

I'm trying to convert an Angular `HTTP.get` function in my `controllers.js` to a service in `services.js`. The examples I have found all have conflicting ways to implement the service and their choice of names is confusing. Furthermore, the actual angular documentation for services uses yet a different syntax than all the examples. I know this is super simple, but please help me out here. I have `app.js`, `controllers.js`, `services.js`, `filters.js`. app.js ``` angular.module('MyApp', []). config(['$routeProvider', function($routeProvider) { $routeProvider. when('/bookslist', {templateUrl: 'partials/bookslist.html', controller: BooksListCtrl}). otherwise({redirectTo: '/bookslist'}); } ]); ``` controllers.js ``` function BooksListCtrl($scope,$http) { $http.get('books.php?action=query').success(function(data) { $scope.books = data; }); $scope.orderProp = 'author'; } ```

Original source