The real secrets behind forRoot and/or forChild of an NgModule

Sometimes you may stumble upon an NgModule which exposes a forRoot() method on its type. This can have a couple of reasons, and one of them should be really important to you.

If the method has parameters, you may have the possibility to provide some configuration. For instance, the RouterModule allows the developer to declare their routes using this method. The interesting thing is, that this is also the only well-known reason for those methods to exist. But that's not the truth. There is something even more important to know about these methods.

First, let's have a look at the return type of the method: ModuleWithProviders

What is the Angular API documentation writing about this type?

A wrapper around a module that also includes the providers.

That's all? Not much, though. So what is the mystery behind this? To reveal this, we have to look a little bit deeper into the way the Angular Router is handling a lazy loaded module (with the loadChildren route property defined). Normally, an imported module uses the top-most injector of the application. This means, if you don't lazy load any modules, the AppInjector is the top-most injector for every module. In that case, when Angular is crawling the modules and their providers through the imports array in the NgModule decorator, all providers get collected in this one injector and, as usually, the last one declared wins.

That is not happening when the module gets lazy loaded. Because of that, Angular can't crawl this module during bootstrap and nothing is known about any providers declared in the providers array of the NgModule decorator. When the module is then loaded, Angular has no chance but to create another injector which is (for a short time) the top-most for that part of the application. The reason for this is that a configured injector cannot be changed afterwards. Of course, if anything is not declared in that new (nested) injector the lookup continues in the parent injector. When you use the providers array in the Component decorator the same thing is happening as well.

Closing the bridge, the ModuleWithProviders type has also a providers array in its definition. If you import your module anywhere in the main application and in lazy loaded modules, its NgModule decorator should not have any providers listed to prevent another instantiation of them. Instead, the module should implement a forRoot() method returning these providers. You are then using this method to import the module in your app module once. At that point the providers get registered into the AppInjector and are available for injection. Every time you are going to import the module by type, no providers are defined in your NgModule decorator and won't get registered another time in a lazy loaded module's injector.

In my opinion this is a much more important secret behind the forRoot() or forChild() convention to bear in mind.


Use Angular template reference variables anywhere in the template... not!

Did you ever use template reference variables in Angular? Maybe you don't remember exactly what they are or represent. Quick and easy they allow you to access either a DOM element or an instance of a component or directive in your current template. They are defined by writing a hash sign (#) together with a name as an additional attribute of the DOM element. If this DOM element is just a plain one the variable contains a reference to it. In that case you can access any property of that DOM element through this variable:

<input type="text" (change)="true" #variable>
{{ variable.value }}

In this example the entered value will be written out when you blur the input (the event listener for change is just for having the change detection run).

If you have a component living on the DOM element the variable will contain the instance of that component (and not the DOM element):

<my-component #variable [input]="'hello'"></my-component>
{{ variable.input }}

And if you want to access the instance of a directive you need to specify which one, because there could be more than one directive existing on that DOM element. The exportAs property of the directive's decorator defines the attribute's value to access that particular instance. For example, the FormsModule's directive for the form DOM element (NgForm) is exporting itself as ngForm. This enables you to e.g. disable a button until the form is valid:

<form #variable="ngForm">
  <!-- some more HTML ... -->
  <button type="submit" [disabled]="variable.form.invalid">Submit!</button>
</form>

Most of the time this works without any problems. But there is a snag in it. First let's take a look what the Angular documentation writes about these variables:

"You can refer to a template reference variable anywhere in the template."

Sounds good. And later the documentation states:

"The scope of a reference variable is the entire template."

Yep, got it. But take a look at the following component's template:

<div *ngIf="true">
  <my-component #variable [input]="'Do you see me?'>
</div>
{{ variable.input }}

What do you think is happening now? Will it show the component input's value "Do you see me?" on the screen? No! It won't. Instead you will get an error in the console:

TypeError: Cannot read property 'input' of undefined

Wait! Didn't the documentation suggest multiple times that these variables can be used anywhere in the template? Yes, and that is still true even it does not look like that for now.

The reason for this is the ngIf directive - or any other directive used together with a star (*). These directives are so called structural directives and the star is just a short form for something more complex. Every time you use a structural directive (ngIf, ngFor, ngSwitchCase, ...) Angular's view engine is desugaring (it removes the syntactical sugar) the star within two steps to the following final form (using the previous ngIf as an example):

<ng-template [ngIf]="true">
  ...
</ng-template>

Did you notice? Something extraordinary emerged out of the previous HTML containing the structural directive - the ng-template node. This node is the reason for limiting the scope of the template reference variable to exactly this inner DOM part only - it defines a new template inside. Because of limiting a variable to its defining template any variable defined within the ng-template (and this means within the DOM part of the ngIf) cannot be used outside of it. It cannot cross the borders of a template.

Huh, so the documentation is right? Yes, but maybe it is not clearly written somewhere that structural directives introduce new nested templates with new barriers for those variables which should be available in the whole template file primarily.


Cordova vs. Zone.js or "Why is Angular's document event listener not in a zone?"

If you put an Angular Single Page Application into a Cordova wrapped application any "document:*" host listener (e.g. "document:click") won't be triggered with a zone update. This means Angular is not running the change detection to see if there is any update to be processed in the view etc.

The reason for this is that Cordova is monkey-patching window.addEventListener and document.addEventListener. But wait! Isn't Zone.js also monkey-patching these, too? Yes, indeed. But this is done on EventTarget's prototype directly. Cordova however is assigning a new function to those methods. And here comes the problematic part:

This is breaking the prototype inheritance. Zone.js is not involved anymore! Now, any event listener added won't run in a zone (and trigger the change detection).

But what could you do? Maybe call run of NgZone every time in your callback? This would trigger a useless global change detection run in a non-Cordova environment. Fairly not the best idea. Could we just some kind of restore the previous prototype inheritance way? Yes we can! But we need to break it by ourself first. ;)

(function () {
  'use strict';

  window.addEventListener = function () {
    EventTarget.prototype.addEventListener.apply(this, arguments);
  };

  window.removeEventListener = function () {
    EventTarget.prototype.removeEventListener.apply(this, arguments);
  };

  document.addEventListener = function () {
    EventTarget.prototype.addEventListener.apply(this, arguments);
  };

  document.removeEventListener = function () {
    EventTarget.prototype.removeEventListener.apply(this, arguments);
  };
})();

That's all? Yes! But what is happening here? Just some fancy JavaScript magic. When these methods get called, the method of the EventTarget prototype will be called right in the new implementation. The this context will be switched to window and all provided arguments will be forwarded. And the secret is that this needs to be done before cordova.js is executed. In that case Cordova is monkey-patching our implementation which is redirecting the call to the prototype  (later monkey-patched by Zone.js).

And there is the zone again!


The new Angular2 Animation DSL

With one of the next Angular2 release candidate (probably RC2) the new Animation DSL (Domain Specific Language) will be introduced. You will then be able to trigger animations by changing properties of your component's class. The coupling is done in the component's template with the new animation prefix @ in front of the trigger's name followed by an expression which is evaluated during change detection:

<div @myAnimationTrigger="myStatusExp">...</div>

The trigger's name is the identifier of the animation which has to be defined in your component's decorator:

@Component({
  selector: 'my-component',
  templateUrl: 'my-component-tpl.html',
  animations: [
    trigger('myAnimationTrigger', [
      state(...),
      state(...),
      transition(...),
      transition(...)
    ])
  ]
})
class MyComponent {
  myStatusExp = "something";
}

At this point you have to use the new Animation DSL to define and control your animations. The reason for choosing an own DSL here is to be independent from DOM-specific environments and Angular may also do some performance optimizations in the background. The language is not complex and quite easy to understand. Basically, you just need to name your animation trigger, define the states which could be the result of your expression (like "expanded", "collapsed", ...) and write your final visual representation of the target element (on which the animation trigger is set in the template) as an object which looks like writing CSS in each of these states. Of course, this could be even more powerful by defining sequences or groups (or both) and even introducing key frames to explicitly define the transition of the styled properties. After defining the states, you declare the duration of the animation when a state (the result of your expression) changes to another one. At this point it is also possible to introduce some in-between animation before the element animates to its final state. That's the theory, but how does it look? I will show you and explain each line:

animations: [                                         // 1
  trigger('openClose', [                              // 2
    state('collapsed, void',                          // 3
      style({ height: '0px', color: 'lightgreen' })), // 4
    state('expanded',                                 // 5
      style({ height: AUTO_STYLE, color: 'red' })),   // 6
    transition('collapsed <=> expanded', [            // 7
      animate(1000)                                   // 8
    ])                                                // 9
  ])                                                  // 10
]                                                     // 11

On line 1 the new property of the component's decorator is shown. It's type is an array where the triggers are declared.

Line 2 is defining our trigger named openClose. This name is used later in the component's template together with the @ prefix.

Beginning with line 3 the first state is defined. This state will be used when the expression returns collapsed. But wait, there is another interesting value in the first parameter: void. The void state is a reserved name and represents the element's visuals when it is not part of the application (like it would be removed or added by ngIf). With this special state you are now able to animate the removal (and addition, of course) of an element with the same mechanism. In the past you may have used the classes ng-enter and ng-leave together with CSS based animations (while the latter was buggy and only the addition could be animated), but this part is completely gone from Angular's code base (so you need to change your animations with one of the next releases - BREAKING CHANGE). The second parameter of the state method is the final state of the element which should be applied when the state is reached.

The style in line 4 represents the visual appearance of the element in the collapsed state and also when the element is added or removed (because of using void in the state's name parameter).

When the expression returns expanded the state defined on line 5 will be used.

A special constant is used as the value in the styles on line 6 for the property height: AUTO_STYLE (which represents internally a string containing an asterisk). In my opinion, this is one of the most awesome parts of this animation framework. You are now able to use current style property values of the element in your animations. With the example written above, the element expands to its content based height! Isn't this crazy? I think so!

In line 7 the transitions of the state are declared. In this example I am using a two-way transition which is represented by <=>. To define them in one direction => should be used instead. Using this notation, you may define a faster or slower animation if the element collapses or expands. You have the power here. Using an asterisk as one of the sides any state would be used at that position (like transition from any state to void would be written as * => void).

Setting the duration of the animation (from the current visual representation to the final representation) is done in line 8. The first parameter can either be a number (which represents milliseconds) or a string using the CSS based notation for a duration. Even easing (by name or as cubic bezier definition) could be used.

That's all. With these lines of code you have a working expand/collapse animation without writing any line of CSS. Here's the code of a component which is using this animation:

import {AUTO_STYLE, Component, trigger, state, animate, transition, style} from '@angular/core';

@Component({
  selector: 'animation-example',
  styles: [`
    .container {
      background-color: white;
      border: 10px solid black;
      width: 200px;
      text-align: center;
      line-height: 100px;
      font-size: 50px;
      box-sizing: border-box;
      overflow: hidden;
    }
  `],
  animations: [
    trigger('openClose', [
      state('collapsed, void',
        style({ height: '0px', color: 'lightgreen' })),
      state('expanded',
        style({ height: AUTO_STYLE, color: 'red' })),
      transition('collapsed <=> expanded', [
        animate(1000)
      ])
    ])
  ],
  template: `
    <button (click)="expand()">Expand</button>
    <button (click)="collapse()">Collapse</button>
    <hr />
    <div class="container" @openClose="animationState">
      Look at this box
    </div>
  `
})
export class AnimationExampleComponent {
  animationState: string;

  constructor() {
    this.collapse();
  }

  expand() {
    this.animationState = 'expanded';
  }

  collapse() {
    this.animationState = 'collapsed';
  }
}

I'm really looking forward to the availability of this this awesome part of Angular2 and hope the Angular team releases it soon.


Tired of waiting for TypeScript compilation?

Compiling (or transpiling) TypeScript into JavaScript takes some time. And with many TypeScript files it takes even longer. But what could you do to speed things up?

There is one compilation option you may stumble upon: isolatedModules

By setting this to true, the compilation times will be incredible fast. But why is this happening? The reason is, that the TypeScript compiler doesn't do any type checking anymore with this option switched on. You may ask yourself "Isn't TypeScript also for explicit type checking and why should I switch this off?". Yes that is true, but during development you should not wait for the transpiler over and over. And if you use a modern IDE (e.g. WebStorm, VS Code) the IntelliSense will guide you and show the type problems during writing the code.

A common gulp task for transpiling TypeScript code with sourcemaps for an Angular2 SPA would look like this (I even don't use a project anymore):

gulp.task('build:scripts', () => {
return gulp.src(['./src/app/**/*.ts', './typings/browser.d.ts'], { base: './src' })
.pipe(sourcemaps.init())
.pipe(typescript({
target: 'ES5',
module: 'system',
moduleResolution: 'node',
sourceMap: true,
emitDecoratorMetadata: true,
experimentalDecorators: true,
removeComments: false,
noImplicitAny: false,
isolatedModules: true
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./build'));
});

Finally you should switch this option to false (which is also the default value), of course, when you build a release version of your code to have an explicit last type check by the compiler. Or think about a build server which also does the type checking after you pushed your changes during continuous integration. There are many ways to ensure that the final result is still completely type checked, but during development you should save this time for better things.


Relative template URLs for Angular2 components

When you write an Angular2 Single Page Application you need the TypeScript compiler to create at least ES5 JavaScript code to be able to run your SPA in a modern browser. If you take a closer look at the resulting code generated by the TypeScript compiler with at least version 1.8.2 you should see that there is a local variable called __moduleName which filled with the id property of the second parameter of the inner function:

System.register(['angular2/core'], function(exports_1, context_1) {
    "use strict";
    var __moduleName = context_1 && context_1.id;
    var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
...

Unfortunately, this variable was always undefined. The reason for this could not be found in the TypeScript compiler's code - it is innocent (for this time, boy). But let's take a closer look at the module system Angular is using. Yes! Starting with SystemJS 0.19.19 life came to this variable. With that version (the most recent version is already 0.19.25 by time of writing of this article) the second parameter was finally provided and the variable was now set to the URL of the current module. Like in my sample it contains the following:

http://localhost:8000/app/components/app/app.js

But what can you do with this information? The key to happiness is to take this value and set it on the moduleId property of the @Component decorator:

@Component({
    moduleId: __moduleName,
    selector: 'my-app',
    templateUrl: 'app.html',
...

To satisfy the TypeScript compiler you first need to declare it as a string right at the beginning of our file:

declare var __moduleName : string;

That was easy. You may already spotted that I put a relative URL into the templateUrl property. How could this work? This is now possible as Angular is using the value you set on moduleId to resolve any relative URLs you may use either in templateUrl or even in styleUrls. And by saying "relative URLs" I mean true relative URLs like "../other.html" (but you may not do this, as a component should be together with it's template etc. at one place).

Finally, no more hassle when you move components between folders (but keep watching the import statements). Good guy, SystemJS.