Angular 2 dependency injection in ES5 and ES6
To use Angular 2 with ES5 you need this script:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.3/angular2-all.umd.js"></script>
This provides an global variable that contains all of Angular 2. Now you can write ng.core.Component
instead of the @Component
annotation. The first parameters of the Constructor are the injectables.
var Component = ng.core
Component({
selector: 'hello-cmp',
template: 'Hello World!',
viewProviders: [Service]
.Class({
constructor: [Service, function (service) {
...
}],
});
And tell the injector that our service parameter is a instance of Service
Component.parameters = [[new ng.core.Inject(Service)]];
The following Exapmle shows the usage of angular2 with ES6:
import {Component} from 'angular2/core';
import {Service} from './example.service';
let componentAnnotation = new Component({
selector: 'world-time',
inputs: ['timeZones'],
providers: [Service],
template: `
...
`
});
export class ComponentExample {
constructor(service) {
this._service = service;
}
...
}
WorldTimeComponent.annotations = [componentAnnotation];
WorldTimeComponent.parameters = [[Service]];
In this plunkr you can find a working ES6 example.
But you can use decorators by using Babel. Enabling the optional[]=es7.decorators
(in webpack) or by setting your configuration to stage:1
.
Injectable
decorator is specific to TypeScript flavour of Angular 2. It enables a class constructor to be implicitly annotated for DI through TypeScript type annotations. It is redundant in TS and unneeded in JS for injected dependencies that are annotated with Inject
.
Angular 2 injectables (classes and constructor functions) are supposed to be annotated with annotations
and parameters
static properties under the hood.
annotations
is an array that contains new
ed decorators for injectable class:
function SomeComponent(...) {}
SomeComponent.annotations = [new Componenent(...)];
parameters
is an array that contains decorators for constructor parameters, each element is an array that contains a list of new
ed decorators for respective constructor property (similarly to $inject
property explicit annotation in Angular 1.x):
function Service(someService, anotherService) {}
Service.parameters = [
[new Inject(SomeService)],
[new Inject(AnotherService), new Optional, new SkipSelf]
];
All class decorators are extended from TypeDecorator
, meaning that they can be called as functions. In this case so-called DSL syntax is used that allows to chain a decorator with Class
helper function:
var SomeComponent = Componenent(...).Class(...);
Class
is also available separately, it constructs a new class from given definition object and allows to annotate constructor
method with array (similarly to inline array explicit annotation in Angular 1.x):
var SomeService = Class({
constructor: [[new Inject(SomeService)], function (someService) {}]
});
Class
helper was deprecated in latest framework versions. It is supposed to be replaced with raw functions or third-party class helpers in ES5. Decorators support direct chaining with class functions, Componenent(...)(ComponentClass)
.
Angular 2/4 ES6 with System.import
An example:
Promise.all([
System.import('@angular/core'),
System.import('@angular/platform-browser'),
System.import('@angular/platform-browser-dynamic')
])
.then(([
{Component, Inject, Injectable, Optional, NgModule, OpaqueToken},
{BrowserModule},
{platformBrowserDynamic}
]) => {
const CONSTANT = { value: 'constant' };
const CONSTANT_TOKEN = new OpaqueToken;
const CONSTANT_PROVIDER = { provide: CONSTANT_TOKEN, useValue: CONSTANT };
class Service {
constructor(constant) {}
}
Service.parameters = [[new Inject(CONSTANT_TOKEN)]];
class AppComponent {
constructor(service, constant) {}
}
AppComponent.annotations = [new Component({
selector: 'app',
template: '...',
providers: [Service, CONSTANT_PROVIDER]
})];
AppComponent.parameters = [[new Inject(Service)], [new Inject(CONSTANT_TOKEN)]];
class AppModule {}
AppModule.annotations = [new NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})];
platformBrowserDynamic().bootstrapModule(AppModule);
})
.catch((err) => console.error(err));
Angular 2/4 ES5 with UMD modules and ng
global
An example:
var Class = ng.core.Class;
var Component = ng.core.Component;
var Inject = ng.core.Inject;
var Injectable = ng.core.Injectable;
var NgModule = ng.core.NgModule;
var OpaqueToken = ng.core.OpaqueToken;
var BrowserModule = ng.platformBrowser.BrowserModule;
var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
var CONSTANT = { value: 'constant' };
var CONSTANT_TOKEN = new OpaqueToken;
var CONSTANT_PROVIDER = { provide: CONSTANT_TOKEN, useValue: CONSTANT };
// Class helper function that uses A1-flavoured inline array DI annotations
// and creates an annotated constructor
var Service = Class({
constructor: [[new Inject(CONSTANT_TOKEN)], function (constant) {
console.log('Service constructor', constant);
}]
});
// can also be
// function Service(constant) {};
// Service.parameters = [[new Inject(...)], ...];
// when not being `new`ed, Component is a chainable factory that has Class helper method
var AppComponent = Component({
selector: 'app',
template: '...',
providers: [Service, CONSTANT_PROVIDER]
})
.Class({
constructor: [
[new Inject(Service)],
[new Inject(CONSTANT_TOKEN)],
function (service, constant) {
console.log('AppComponent constructor', service, constant);
}
]
});
// can also be
// function AppComponent(...) {};
// AppComponent.annotations = [new Component(...)];
// AppComponent.parameters = [[new Inject(...)], ...];
var AppModule = NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
.Class({ constructor: function () {} });
// can also be
// function AppModule() {};
// AppModule.annotations = [new NgModule(...)];
platformBrowserDynamic().bootstrapModule(AppModule);