Reputation: 1528
I have this class-defined component (transpiled later by webpack and babel back into ES5). I need to use the $http service in one of its methods. How do I do that? Where do I inject $http as a dependency? If I do it in the constructor arguments, I get an error as if I hadn't injected it at all. Maybe classes is not the way to go here?
angular.module('myApp').component('home', {
template: require('./home.component.html'),
controller: class HomeCtrl {
constructor() {
}
doMe() {
$http.get('http://www.yahoo.com/');
}
}
});
Upvotes: 8
Views: 3760
Reputation: 48212
ES2015 classes (or transpiled classes) are just syntactic sugar over prototypal inheritance. What this means is that the methods you define are put on the prototype of the "class". In order to be able to access the dependencies injected in the constructor, you need to somehow store them for later reference by the prototype method.
This is usually done by putting them on the instance:
function HomeController($http) {
this.$http = $http;
}
HomeController.prototype.doMe = function() {
this.$http.get('http://www.yahoo.com/');
};
In class-based syntax this translates to:
class HomeController {
constructor($http) {
this.$http = $http;
}
doMe() {
this.$http.get('http://www.yahoo.com/');
}
}
EDIT:
If you are using TypeScript, you can save some boilerplate by using access modifiers on the constructor arguments. E.g.:
class HomeController {
constructor(private $http) {}
}
...which is shorthand for:
class HomeController {
private $http;
contructor($http) {
this.$http = $http;
}
}
EDIT 2:
If you want to make your controller minification-friendly, you can use one of the options described here (possibly along with a tool like ngAnnotate). For example, this is how you could use the "$inject
Property Annotation" method:
ES5
HomeController.$inject = ['$http'];
function HomeController($http) {...}
HomeController.prototype.doMe = function() {...}
ES2015
class HomeController {
constructor($http) {...}
doMe() {...}
}
HomeController.$inject = ['$http'];
// OR
class HomeController {
static get $inject() { return ['$http']; }
constructor($http) {...}
doMe() {...}
}
TypeScript
class HomeController {
static $inject = ['$http'];
constructor(private $http) {}
doMe() {...}
}
Upvotes: 11
Reputation: 1528
In the end, I did:
controller: class {
constructor($http, Restangular, $state) {
Object.assign(this, {$http, Restangular, $state});
}
doMe() {
// use this.$http, this.Restangular & this.$state freely here
}
}
Upvotes: 0
Reputation: 222369
The class should have explicit $inject
annotation in order to be properly minified:
class HomeCtrl {
static get $inject() {
return ['$http'];
}
// or unstandardized shortcut:
// static $inject = ['$http'];
constructor($http) {
this.$http = $http;
}
doMe() {
this.$http...
}
}
Upvotes: 3