Services with ES6 (AngularJS)

jeffarese picture jeffarese · Apr 15, 2015 · Viewed 11.2k times · Source

I'm having problems accessing Angular built-in services such as $http when creating a service with ES6.

For example, I'm creating a "ResultsFinder" service that will do an AJAX call and then do some stuff. The problem is that I only have access to $http on the constructor (if I pass it as an argument), but not on other methods (such as getResults).

See this code example:

Inside getResults I don't have access to $http. In order to have access I should do something that I don't feel right like this:

(() => {
  'use strict';

  class ResultsFinder {
    constructor($http) {
      this.$http = $http;
    }
    getResults() {
      // Here I have access to this.$http
      return 'ResultsFinder';
    }
  }

  /**
   * @ngdoc service
   * @name itemManager.service:ResultsFinder
   *
   * @description
   *
   */
  angular
    .module('itemManager')
    .service('ResultsFinder', ResultsFinder);
}());

Anyone can give me some advice about the proper way to handle this?

Answer

Martin picture Martin · Apr 15, 2015

You need to use this.$http inside your getResults method.

(() => {
  'use strict';
      
class ResultsFinder {
	
    static $inject = ['$http'];   
    constructor($http) {
        this.$http = $http;
    }
		
    getResults() {
        return this.$http.get('/foo/bar/');
    }
}

  /**
   * @ngdoc service
   * @name itemManager.service:ResultsFinder
   *
   * @description
   *
   */
  angular
    .module('itemManager')
    .service('ResultsFinder', ResultsFinder);
}());

As a side note, I added a static $inject "annotation" to your class. This is a best practice if you are not using something like ngAnnotate. It also makes it easier to change out implementations by only changing the $inject values.

If you are a ES5 developer it may help to think about how this would look in ES5

ResultsFinder.$inject = ['$http'];
var ResultsFinder = function($http) {
    this.$http = $http;
}

ResultsFinder.prototype.getResults = function() {
    return this.$http.get('/foo/bar/');
}

NOTE

Since you are using ES6, should probably use ES6 modules to organize your code.

You define and export your angular-module within an ES6 module:

import {module} from 'angular';

export var itemManager = module('itemManager', []);

Then import the Angular module

import {itemManager} from '../itemManager';

class ResultsFinder {

    static $inject = ['$http'];   
    constructor($http) {
        this.$http = $http;
    }

    getResults() {
        return this.$http.get('/foo/bar/');
    }
}

itemManager.service('ResultFinder', ResultFinder);