Defining dependencies for injection – Aurelia

There are two ways to define dependencies which you would like injected into your objects in Aurelia:

  1. Use the `inject` decorator
  2. Use the static `inject` member

Using the static inject member has the benefit of not needing to import `inject` from the aurelia-framework:

import {Todo} from './todo';
import {Factory} from 'aurelia-dependency-injection';
import {EventAggregator} from 'aurelia-event-aggregator';

export class App {
  static inject = [EventAggregator, Factory.of(Todo)];
  constructor(aggregator, todoFactory) {
    this.bus = aggregator;
    this.completedTodos = 0;
    this.newTodoDesc = '';
    this.todos = [];
    this.todoFactory = todoFactory;
  }
}

 

Creating instances of objects with dependencies – Aurelia

Sometimes you want to create instances of objects with dependencies, which would normally have been created by the DI container within Aurelia.

Aurelia implements a Factory object which can be used to create instances out of the DI container on demand, for any of your objects:

import {Todo} from './todo';
import {Factory} from 'aurelia-dependency-injection';
import {EventAggregator} from 'aurelia-event-aggregator';

export class App {  

  static inject = [EventAggregator, Factory.of(Todo)];
  constructor(aggregator, todoFactory) {
    this.bus = aggregator;
    this.completedTodos = 0;
    this.newTodoDesc = '';
    this.todos = [];
    this.todoFactory = todoFactory;
  }

  addTodo() {
    if (!this.newTodoDesc) return;

    let todo = this.todoFactory();
    todo.description = this.newTodoDesc;
    this.todos.push(todo);
    this.newTodoDesc = '';
  }
}

 

Detect changes to model state – Aurelia

In order to intercept or subscribe to changes in your model, you need to decorate the properties you’re interested in with observable and implement the convention based <propertyName>Changed function:

import {observable} from 'aurelia-framework';

export class Todo {
  @observable done = false;
  description = '';

  doneChanged(newVal, oldVal) {
    console.log(`done change from ${oldVal} to ${newVal}`);
  }
}

 

Aurelia CLI and template requires

So you’ve used the Aurelia CLI to bootstrap your awesome Aurelia app and you npm install some dependencies, let’s say bootstrap and jquery:

npm i bootstrap 
npm i jqeury

Ok, ready to rock. Next, you update your aurelia.json file with the new dependencies:

"jquery",
{
  "name": "bootstrap",
  "path": "../node_modules/bootstrap/dist",
  "main": "js/bootstrap.min",
  "deps": ["jquery"],
  "exports": "$"
}

Sweet.

Next up is to import bootstrap into your main module, so that you can require it in your templates:

import 'bootstrap';

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .feature('resources');

  aurelia.start().then(() => aurelia.setRoot());
}

Amazeballs.

So, you require your bootstrap css in your app template:

<template>
  <require from="bootstrap/css/bootstrap.css"></require>
  <require from="./styles.css"></require>

  <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">
        <i class="fa fa-user"></i>
        <span>Contacts</span>
      </a>
    </div>
  </nav>

  <div class="container">
    <div class="row">
      <div class="col-md-4">Contact List Placeholder</div>
      <router-view class="col-md-8"></router-view>
    </div>
  </div>
</template>

But, what’s this??? You get this error in the console:

vendor-bundle

WTF is going on there? Hmmm… Let’s review that dependency configuration we added to aurelia.json…

Oooh, we left out the css resources:

{
  "name": "bootstrap",
  "path": "../node_modules/bootstrap/dist",
  "main": "js/bootstrap.min",
  "deps": ["jquery"],
  "exports": "$",
  "resources": [
    "css/bootstrap.css"
  ]
}

And now it works.