28

Was the angular2 dependency injection container designed for standalone use, and is it possible to use it for typescript/javascript server-side applications ?

I opened an issue on Oct. 16 (https://github.com/angular/di.js/issues/108) on the di project which was I guess supposed to make it into v2. Apparently this was not possible. What's up with the new angular2 di ? Can I use it in a standalone fashion with js / es6 / ts projects?

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
Ludovic C
  • 2,855
  • 20
  • 40
  • 3
    In the issue you linked, `It is not easy to use it as standalone atm and there is no documentation for such setup. There is a plan to extract DI library from the **angular2** repo in the future, but this is not the case today.` Also, nice hat! – 0xcaff Dec 25 '15 at 02:41
  • It's speaking about the angular2 di. – 0xcaff Dec 25 '15 at 02:43
  • Oh I see you're right. But things might have changed now! Angular2 wasn't out at the time. – Ludovic C Dec 25 '15 at 02:48
  • [We had alpha 44](https://github.com/angular/angular/commit/169cb5f270c0a8f570a9383bb7ddbc4d30ec6b5f) on October 15th. – 0xcaff Dec 25 '15 at 02:51
  • 1
    "It’s an isolated component of the framework that can be used as standalone system, without Angular 2 " http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html – Ludovic C Dec 25 '15 at 02:54
  • 1
    That's the thing. I'm reading all sort of stuff all over the place. I'd like to know once for all if I can use angular2 Di elsewhere. – Ludovic C Dec 26 '15 at 17:41

6 Answers6

6

As of Angular 2 RC.5, DI is a part of @angular/core package. For non-Angular uses, it was recently extracted into injection-js package by Minko Gechev, a member of Angular team.

Here is a short ES6, Node-friendly example:

// may not be needed for injection-js and recent @angular/core versions
// if ES5-flavoured `Class` helper isn't used
require('reflect-metadata');

const { Inject, Injector, ReflectiveInjector, OpaqueToken } = require('@angular/core');
// or ... = require('injection-js');

const bread = new OpaqueToken;
const cutlet = new OpaqueToken;

class Sandwich {
    constructor(bread, cutlet, injector) {
        const anotherBread = injector.get('bread');

        injector === rootInjector;
        bread === 'bread';
        anotherBread === 'bread';
        cutlet === 'cutlet';
    }
}

Sandwich.parameters = [
    new Inject(bread),
    new Inject(cutlet),
    new Inject(Injector)
];

const rootInjector = ReflectiveInjector.resolveAndCreate([
    { provide: 'bread', useValue: 'bread' },
    { provide: bread, useValue: 'bread' },
    { provide: cutlet, useValue: 'cutlet' },
    Sandwich
]);

const sandwich = rootInjector.get(Sandwich);
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • thanks, why do you use `Sandwich.parameters=[new Inject(bread)...` instead of `constructor(new Inject(bread)...) {`? – Max Koretskyi Feb 16 '17 at 10:44
  • @Maximus `parameters` static property is how the decorators are translated to ES5/ES6 (notice that there may be multiple decorators per constructor param, i.e Inject Optional). See also https://angular.io/docs/ts/latest/cookbook/ts-to-js.html#!#dependency-injection . – Estus Flask Feb 16 '17 at 10:52
  • @Maximus You can also check this question, it addresses this http://stackoverflow.com/a/39029435/3731501 – Estus Flask Feb 16 '17 at 10:54
  • I see, thanks. I think it's due to the fact that plain ES6 doesn't support decorators, right? Because I just checked transpiled ES5 code and it doesn't have `parameters`. It looks like this `Car = __decorate([ __param(0, injection_js_1.Inject(engine_1.Engine)),` – Max Koretskyi Feb 16 '17 at 10:59
  • @Maximus Yes. The framework is heavily TS-oriented, it was the best common denominator they could come up with. It looks a bit more readable with `Class` helper which allows to annotate a constructor with an array, AngularJS style. – Estus Flask Feb 16 '17 at 11:03
6

Seems someone has extracted dependency injection from Angular2 recently(Jan 2017), which allow it to use outside of the framework.

https://github.com/mgechev/injection-js

Vincent Pang
  • 422
  • 4
  • 8
  • 1
    Just noticed your answer after I've updated my own with this information. That's very good news, because mgechev is active A2 developer, so the repo will surely be up to date. – Estus Flask Jan 26 '17 at 09:14
5

I doubt it, it doesn't look like it has been extracted into a component. It's a bit sad that major frameworks like Angular still have this monolithic approach, I would rather like to see Component oriented frameworks like Symfony, but JavaScript isn't quite there yet.

In the meantime you have InversifyJS that doesn't look bad.

Théo
  • 655
  • 7
  • 17
  • 1
    It inconvenient that DI is mixed with non-relevant stuff, but core A2 features don't depend on the platform, so it should be possible at least, just not sure how good the things are (NPM package is relatively small and contains pre-built ES5 and ES6). Btw, we already got [Aurelia DI](https://github.com/aurelia/dependency-injection) as a componentized alternative, not documented for Node usage too. – Estus Flask Aug 08 '16 at 22:40
5

At the moment the Angular 2.0 DI code doesn't seem to be ready to be consumed by other libraries.

I would like to suggest an alternative. I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings. It works in both node and browsers and some parts of its API are based on the Angular 2 DI API.

You need to follow 3 basic steps to use it:

1. Add annotations

The annotation API is based on Angular 2.0:

import { injectable, inject } from "inversify";

@injectable()
class Katana implements IKatana {
    public hit() {
        return "cut!";
    }
}

@injectable()
class Shuriken implements IShuriken {
    public throw() {
        return "hit!";
    }
}

@injectable()
class Ninja implements INinja {

    private _katana: IKatana;
    private _shuriken: IShuriken;

    public constructor(
        @inject("IKatana") katana: IKatana,
        @inject("IShuriken") shuriken: IShuriken
    ) {
        this._katana = katana;
        this._shuriken = shuriken;
    }

    public fight() { return this._katana.hit(); };
    public sneak() { return this._shuriken.throw(); };

}

2. Declare bindings

The binding API is based on Ninject:

import { Kernel } from "inversify";

import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";

var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);

export default kernel;

3. Resolve dependencies

The resolution API is based on Ninject:

import kernel = from "./inversify.config";

var ninja = kernel.get<INinja>("INinja");

expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true

The latest release (2.0.0) supports many use cases:

  • Universal JavaScript (Works in Node.js and Browsers)
  • Kernel modules
  • Kernel middleware
  • Use classes, string literals or Symbols as dependency identifiers
  • Injection of constant values
  • Injection of class constructors
  • Injection of factories
  • Auto factory
  • Injection of providers (async factory)
  • Activation handlers (used to inject proxies)
  • Multi injections
  • Tagged bindings
  • Custom tag decorators
  • Named bindings
  • Contextual bindings
  • Friendly exceptions (e.g. Circular dependencies)

You can learn more about it at https://github.com/inversify/InversifyJS

Remo H. Jansen
  • 23,172
  • 11
  • 70
  • 93
  • 1
    The answer is somewhat guilty of hijacking and doesn't address the question directly, although it appears that it is certainly possible to use Angular 2 DI with Node (see my own answer). I personally enjoyed it and found it useful in the context. – Estus Flask Aug 15 '16 at 22:27
1

Checkout ubiquits sources - he did somehow integrated angular 2's DI on the backend.

If you want simple but powerfull and painless dependency injection tool for typescript and node.js typedi. It works great with angular frontends too. Also checkout other repositories of this author, there are lot of components that will help you to build node applications using TypeScript.

pleerock
  • 18,322
  • 16
  • 103
  • 128
1

There is an awesome port of the Angular DI: https://github.com/mgechev/injection-js

vlio20
  • 8,955
  • 18
  • 95
  • 180
  • Isn't this the same library as is mentioned in this answer: https://stackoverflow.com/a/41813596/578411? – rene Aug 13 '17 at 15:43