Skip to content

Dependency Injection

Brod edited this page Jun 27, 2018 · 7 revisions

Dependency Injection allows sharing of state throughout hyperbolé.

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 $hyperbole which can be used as a reference to your Hyperbole() instance.

routes/main.ts

import { Hyperbole } from 'hyperbole';
import { AccountTemplate } from '../templates';

const hyperbole = new Hyperbole(); // hyperbole instance

@Route('/account')
export class AccountRoute {
  static $templates = [AccountTemplate];
  constructor(
    @Inject('$hyperbole') private $hyperbole: Hyperbole,
  ) {}

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

hyperbole.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 { Hyperbole } from 'hyperbole';
import { NotificationProvider, WebsocketProvider } from '../providers';

const hyperbole = new Hyperbole();

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

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';export class AccountProvider {
  static $provider = '$account';
  static $inject = ['$notif'];
  constructor(
    private $notif: NotificationProvider,
  ) {}
  ...
}

providers/notification.ts

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

templates/notification.ts

import { Hyperbole } from 'hyperbole';
import { NotificationProvider } from '../providers';export class NotificationTemplate {
  static $selector = '[notification]';
  static $inject = ['$notif'];
  constructor(
    private renderer: Hyperbole.template.render,
    private $notif: NotificationProvider,
  ) {}
  ...
}

Templates

The first argument to the Template constructor is always the Hyperbole.template.render and any dependencies will be injected after that. 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 { NotificationProvider } from '../providers';

export class AccountProvider {
  static $provider = '$account';
  static $inject = ['$notif'];
  constructor(
    private $notif: NotificationProvider,
  ) {}
}