Skip to content

Dependency Injection

Brod edited this page Jul 14, 2018 · 7 revisions

Dependency Injection allows sharing of state throughout Jagwah.

Overview

Dependency injection allows Providers, Templates and Routes to access state information throughout your web application. The only module which supports being injected as a dependency is Providers, in the future you may be able to inject Templates into other Templates.

Usage

To use dependency injection, set a static $inject property on either a Provider, Template or Route with the names of the dependencies you wish to inject. By default all Providers are available for injection, to learn more checkout the Providers naming documentation.

For convienience there is a built in Provider named $jagwah which can be used as a reference to your Jagwah() instance.

routes/main.ts

import { Jagwah, Route, Templates } from 'jagwah';
import { AccountTemplate } from '../templates';

const jagwah = new Jagwah(); // jagwah instance

@Route('/account')
@Templates([AccountTemplate])
export class AccountRoute {
  constructor(
    @Inject('$jagwah') private $jagwah: Jagwah,
  ) {}

  public async before(ctx: any) {
    this.$jagwah... // jagwah instance
  }
}

jagwah.route(AccountRoute)

Dependency Order

The order of dependencies between the static $inject property and the constructor arguments must match, otherwise dependencies will be injected in the wrong order.

import { Jagwah } from 'jagwah';
import { NotificationProvider, WebsocketProvider } from '../providers';

const jagwah = new Jagwah();

@Provider('$account')
export class AccountProvider {
  static $inject = [
    '$notif', // dependency 0
    '$websocket' // dependency 1
  ];
  constructor(
    private $notif: NotificationProvider, // dependency 0
    private $websocket: WebsocketProvider, // dependency 1
  ) {}
}
jagwah.provider(AccountProvider);

@Inject Decorator Note

Dependency order is redundant when using the @Inject decorator as the order of dependencies can be inferred.

Providers

Only a single instance of each Provider will be created, this allows you to inject a Notification Provider into an Account Provider to spawn notifications and then inject the same Notification Provider instance into a Notification Template that can show all those notifications.

providers/account.ts

import { NotificationProvider } from '../providers';
​
@Provider('$account')
export class AccountProvider {
  constructor(
    @Inject('$notif') private $notif: NotificationProvider,
  ) {}
  ...
}

providers/notification.ts

@Provider('$notif')
export class NotificationProvider {
  public notifications: INotification[] = [];
  constructor() {}
  ...
}

templates/notification.ts

import { NotificationProvider } from '../providers';
​
@Template('notification-template')
@Selector('#notification')
export class NotificationTemplate {
  constructor(
    @Inject('$notif') private $notif: NotificationProvider,
  ) {}
  render(renderer: Jagwah.template.render) {
    ...
  }
  ...
}

Templates

Templates are constructed on each use and cannot be injected into other Templates, Providers or Routes.

Routes

Like Providers, only a single instance of each Route will be created and you cannot use Routes as a dependency - to inject Providers into Routes use the static $inject property.

import { AccountProvider } from '../providers';

@Route('/account')
export class AccountRoute {
  constructor(
    @Inject('$account') private $account: AccountProvider,
  ) {}
}