Understanding NgZone

Angular 2 does a lot of things differently from Angular 1, and one of its greatest changes is in change detection. understanding how it works has been essential, particularly when using Protractor for E2E testing. This explores how to work with zones for testing and performance.

A live example of the mentioned code is here.

The biggest change in how Angular 2 handles change detection, as far as a user is concerned, is that it now happens transparently through zone.js.

This is very different from Angular 1, where you have to specifically tell it to synchronise – even though both the built in services and the template bindings do this internally. What this means is, while $http or $timeout do trigger change detection, if you use a third party script, your Angular 1 app won’t know anything happened until you call $apply().

Angular 2, on the other hand does this entirely implicitly –  all code run within the app’s Components, Services or Pipes exists inside that app’s zone, and just works.

So, what is a zone?

zone.js’s zones are actually a pretty complicated concept to get our head around. Running the risk of over-simplifying, they can be described simply as managed code calling contexts – closed environments that let you monitor, control, and react to all events, from asynchronous tasks to errors thrown.

The reason this works is, inside these zones, zone.js overrides and augments the native methods – Promises, timeouts, and so on, meaning your code doesn’t need to know about zone to be monitored by it. Everytime you call setTimeout, for instance, you unwillingly call an augmented version, which zone uses to keep tabs on things. 

What Angular does is use zone.js to create it’s own zone and listen to it, and what this means for us as angular users is this – all code run inside an angularapp is automatically listened to, with no work on our part.

Most times, this works just fine – all change detection “just works” and Protractor will wait for any asynchronous code you might have. But what if you don’t want it to? There are a few cases where you might want to tell angular not to wait for / listen to some tasks:

  • An interval to loop an animation
  • A long-polling http request / socket to receive regular updates from a backend
  • A header component that listens to changes in the Router and updates accordingly

These are cases where you don’t want angular to wait on asynchronous tasks/ change detection to run every time they run.

Control where your code runs with NgZone

NgZone gives you back control of your code’s execution. There are two relevant methods in NgZone – run and runOutsideAngular:

  • runOutsideAngular runs a given function outside the angular zone, meaning its code won’t trigger change detection.
  • run runs a given function inside the angular zone. It is meant to be run inside a block created by runOutsideAngular, to jump back in, and tell angular to start listening again.

So, this code will have problems being tested, as the app will be constantly unstable:

this._sub = Observable.timer(1000, 1000)
    .subscribe(i => {
    this.content = "Loaded! " + i;
});
this.ngZone.runOutsideAngular(() => {
    this._sub = Observable.timer(1000, 1000)
        .subscribe(i => this.ngZone.run(() => {
            this.content = "Loaded! " + i;
        }));
});

Simplifying usage

After understanding how NgZone works, we can simplify its usage, so that we don’t need to sprinkle NgZone.runOutsideAngular and NgZone.run all over the place.

We can create a NgSafeZone service to do exactly that, as the most common use case for this is:

  • Subscribe to an Observable outside the angular zone
  • Return to the angular zone when reacting to that Observable.
@Injectable()
export class SafeNgZone {

    constructor(private ngZone: NgZone) {}

    safeSubscribe(
        observable: Observable < T > ,
        observerOrNext ? : PartialObserver < T > | ((value: T) => void),
        error ? : (error: any) => void,
        complete ? : () => void) {
        return this.ngZone.runOutsideAngular(() =>
            return observable.subscribe(
                this.callbackSubscriber(observerOrNext),
                error,
                complete));
    }

    private callbackSubscriber(obs: PartialObserver < T > |
        ((value: T) => void)) {
        if (typeof obs === "object") {
            let observer: PartialObserver < T > = {
                next: (value: T) => {
                    obs['next'] &&
                        this.ngZone.run(() => obs['next'](value));
                },
                error: (err: any) => {
                    obs['error'] &&
                        this.ngZone.run(() => obs['error'](value));
                },
                complete: () => {
                    obs['complete'] &&
                        this.ngZone.run(() => obs['complete'](value));
                }
            };

            return observer;
        } else if (typeof obs === "function") {
            return (value: T) => {
                this.ngZone.run(() => obs(value));
            }
        }
    }
}

With this the previous code gets simplified quite a bit:

// The following:
this.ngZone.runOutsideAngular(() => {
    this._sub = Observable.timer(1000, 1000)
        .subscribe(i => this.ngZone.run(() => {
            this.content = "Loaded! " + i;
        }));
});

// Becomes:
this._sub = this.safeNgZone.safeSubscribe(
    Observable.timer(1000, 1000),
    i => this.content = "Loaded! " + i);

 

Using TemplateRef to create a tooltip/popover directive in Angular 2

This post is about a Component created in the context of our application development. There is a demo here, and you can find the full source code here.

Lately, the need arose to create a tooltip directive. This brought up a lot of questions we hadn’t had to face before, such as how to create markup wrapping around rendered content, or rather “what is Angular 2’s transclude?”

Turns out, using TemplateRef is very useful for this, but the road to understanding it wasn’t easy. After seeing it used in a similar fashion by Ben Nadel, I decided to take a stab at it.

TemplateRef is used when using <template> elements, or perhaps most commonly when using *-prefixed directives such as NgFor of NgIf. For *-prefixed directives (or directives in <template> elements, TemplateRef can be injected straight into the constructor of the class. For other components, however, they can be queried via something like the ContentChild decorator.

Initially, I had thought to create two directives: a TooltipDirective to be placed on the parent element, plus a TooltipTemplate directive to be placed in a template, that would then inject itself into the parent. It proved too complex, though, and after finding what could be done with the ContentChild query the implementation became much simpler.

The end result looks like this (simplified for clarity):

@Directive({
    selector: "[tooltip]"
})
export class TooltipDirective implements OnInit {
    @Input("tooltip") private tooltipOptions: any;
    @ContentChild("tooltipTemplate") private tooltipTemplate: TemplateRef < Object > ;

    private tooltip: ComponentRef < Tooltip > ;
    private tooltipId: string;

    constructor(
        private viewContainer: ViewContainerRef,
        public elementRef: ElementRef,
        private componentResolver: ComponentResolver,
        private position: PositionService) {
        this.tooltipId = _.uniqueId("tooltip");
    }

    ngOnInit() {
        // Attach relevant events
    }

    private showTooltip() {
        if (this.tooltipTemplate) {
            this.componentResolver.resolveComponent(Tooltip)
                .then(factory => {
                    this.tooltip = this.viewContainer.createComponent(factory);
                    this.tooltip.instance["content"] = this.tooltipTemplate;
                    this.tooltip.instance["parentEl"] = this.elementRef;
                    this.tooltip.instance["tooltipOptions"] = this.options;
                });
        }
    }

    private hideTooltip() {
        this.tooltip.destroy();
        this.tooltip = undefined;
    }

    private get options(): TooltipOptions {
        return _.defaults({}, this.tooltipOptions || {}, defaultTooltipOptions);
    }
}

@Component({
    selector: "tooltip",
    template: `<div class="inner">
<template [ngTemplateOutlet]="content"></template>
</div>
<div class="arrow"></div>`
})
class Tooltip implements AfterViewInit {
    @Input() private content: TemplateRef < Object > ;
    @Input() private parentEl: ElementRef;
    @Input() private tooltipOptions: TooltipOptions;

    constructor(
        private positionService: PositionService,
        public elementRef: ElementRef) {}

    private position() {
        // top and left calculated and set
    }

    ngAfterViewInit(): void {
        this.position();
    }
}

The TooltipDirective requires a <template #tooltipTemplate> element, that gets rendered through a  Tooltip Component, created and injected with the templateRef containing our content. Essentially, “transcluding” it. The Tooltip component’s role is only to wrap the content with some light markup, and position itself when inserted into the page.

A lot of the actual positioning (not shown here, but in the source code) is done directly to the rendered elements, though – I faced some issued when using the host properties object, that I believe were reintroduced in the latest RC.

All in all, it was a great learning experience, and Angular 2’s <template> surely beats Angular.js’ transclude. Slowly but surely Angular 2 get’s more and more demystified to me, but it is hard work getting there.

A breadcrumb component for @ngrx/router

@ngrx/router is, at the moment, one of the best choices for a router component in Angular 2, and Vladivostok, the third iteration of Angular 2’s official router, will take a very heavy inspiration from it. At the moment we are using it to handle our routes, and the need arose to create a breadcrumb component for certain parts of the application.

You can see a working example here.

@ngrx/router‘s API is very light and sparse, but not necessarily incomplete – a lot of the actual implementation is assumed to be left in the hands of the user. This is powered by the use of Observables for Route, RouteParams, QueryParams, etc. A great example of this assumption is the fact that instead of a set of interfaces like CanReuse/CanActivate/CanDeactivate, the router only ever activates components when they change after a route change – any changes in parameters are handled manually by default. More work, but also a clearer image of what one can and cannot do with the tool, and a lot more control.

The first thing we found was that routes have a property – options – that serves the express purpose of holding custom data. A simple usage is this:

export const routes: Route[] = [{
    path: '/',
    component: Home,
    options: {
        breadcrumb: 'Home Sweet Home'
    },
    children: [{
            path: '/component-a',
            component: ComponentA,
            options: {
                breadcrumb: 'A Component'
            },
            children: [{
                    path: '/one',
                    component: One,
                    options: {
                        breadcrumb: 'The One'
                    }
                },
                [...]
            ]
        },
        [...]
    ]
}, ];

And the breadcrumb component is as such:

@Component({
    selector: 'breadcrumbs',
    directives: [NgFor],
    template: `<span>
<span *ngFor="let breadcrumb of breadcrumbs; let isLast = last">
<a [linkTo]="breadcrumb.path">{{breadcrumb.name}}</a>
<span *ngIf="!isLast"> &gt; </span>
</span>
</span>`
})
export class Breadcrumbs {
    private breadcrumbs: any[];

    constructor(private routerInstruction: RouterInstruction) {
        this.routerInstruction
            .subscribe(
                match => {
                    this.breadcrumbs = this.getBreadcrumbs(match);
                }
            );
    }

    private getBreadcrumbs(match: Match) {
        let breadcrumbs = [];
        let path = '';

        for (let i = 0; i < match.routes.length; i++) {
            path = path[path.length - 1] === '/' ? path.substr(0, path.length - 1) : path;
            path += match.routes[i].path ? this.makePath(match.routes[i], match) : '';
            if ((match.routes[i].options || {}).breadcrumb) {
                breadcrumbs.push({
                    name: match.routes[i].options.breadcrumb,
                    path: path
                });
            }
        }

        return breadcrumbs;
    }

    private makePath(route: Route, match: Match) {
        return pathToRegexp.compile(route.path)(match.routeParams);
    }
}

RouterInstruction is one Observable that gives us all the information we need. By watching it, a Match object containing the array of matched routes is returned. All that was left was to create the urls, as @ngrx/router uses only url strings (as opposed to the array notation you’ll find in @angular/router, for instance) – but as @ngrx/router uses path-to-regexp to parse urls, to it was only a matter of using it to compile from the parsed data, and get the urls.

All in all, a very simple solution. Omitted are the use of translations and using asynchronously loaded data (like a profile name) in the breadcrumb – the former is trivial and very unrelated, and the latter we are using stores for, and it’s perhaps a good topic for another post.

Using Class inheritance to hook to Angular 2 component lifecycle

I was thinking of a way to use class inheritance to hook to certain Component lifecycle hooks, without needing to worry about them in the extending class (no knowledge needed, no super() calls to forget about). This does mean “straying off the path”  a little bit, and there may be better ways to do this.

Observables in angular2 are a powerful thing. Unlike the Angular 1 hero, Promises, they represent streams of asynchronous data, and not just single events. This means that a subscription of an observable doesn’t have an end, not necessarily.

Using ngrx/router, I found myself using them a lot, but precisely because they are streams, they need careful cleanup, or we risk leaving a subscription running after a Component has been destroyed.

A typical way we can do this is using ngOnDestroy:

export class Component implements OnDestroy {
    private subscription: Subscription;
    private count: number;

    constructor(private pingService: PingService) {
        let func = this.ngOnDestroy;

        this.subscription = this.pingService.ping
            .subscribe(
                ping => {
                    this.count = ping;
                }
            );
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}

Simple enough when on its own, but something that is sure to add a lot of code repetition and complexity to a complex class with more than one subscription. We can automate this, and the best way I found was to extend a base class:

export class SafeUnsubscriber implements OnDestroy {
    private subscriptions: Subscription[] = [];

    protected safeSubscription(sub: Subscription): Subscription {
        this.subscriptions.push(sub);
        return sub;
    }

    ngOnDestroy() {
        this.subscriptions.forEach(element => {
            !element.isUnsubscribed && element.unsubscribe();
        });
    }
}

This makes the previous class simpler:

export class Component extends SafeUnsubscriber {
    private count: number;

    constructor(private pingService: PingService) {
        let func = this.ngOnDestroy;

        let subscription = this.pingService.ping
            .subscribe(
                ping => {
                    this.count = ping;
                }
            );

        this.safeSubscription(subscription);
    }
}

Which is great, but what if we need to use ngOnDestroy on the parent? Conventional inheritance allows us to use super.ngOnDestroy() but in this particular case, I don’t want to leave this as a possibility, but rather always unsubscribe on destroy, regardless of wether or not ngOnDestroy was overwritten.

So in this case, a little hack is acceptable, in my opinion – we can make sure the unsubscriber code always runs on ngOnDestroy, and both prevent mistakes by omission and make the code cleaner in the user:

export class SafeUnsubscriber implements OnDestroy {
    private subscriptions: Subscription[] = [];

    constructor() {
        let f = this.ngOnDestroy;

        this.ngOnDestroy = () => {
            f();
            this.unsubscribeAll();
        };
    }

    protected safeSubscription(sub: Subscription): Subscription {
        this.subscriptions.push(sub);
        return sub;
    }

    private unsubscribeAll() {
        this.subscriptions.forEach(element => {
            !element.isUnsubscribed && element.unsubscribe();
        });
    }

    ngOnDestroy() {
        // no-op
    }
}

Now, even if ngOnDestroy gets overwritten, the private method unsubscribeAll still runs, as the constructor (which always runs, as typescript requires it)  makes sure this happens. ngOnDestroy, on the other hand, only exists as a noop function, to ensure the code runs regardless of whether  or not one was set in the parent component.

How does this work, then? Javascript (and typescript, by extension) uses prototypal inheritance, which means that super is the prototype – this is the reason why typescript makes it mandatory to call super() in the extending Class constructor, before any references to this – so class inheritance expectations are guaranteed. By changing this.ngOnDestroy on the Base Class constructor, we are essentially adding a property to the instance, essentially overriding the prototype – which happens to be a call to the prototype’s version followed by our own.

Pretty dangerous stuff, but pretty useful as well.

SVG’s FuncIRI, angular2, and the base tag

cog-wrong
Broken mask link: a visualization

I tried to make this title as descriptive and, let’s face it, clickbait-y, because this was hard enough for me to discover. I somehow had never had to deal with this issue until a few days ago – svgs do not play well with single page apps when routing using HTML location is mixed with a set <base> tag.

Specifically, what doesn’t work is anything that uses FuncIRI, or css-style urls. That means <use>, clip-path and filter tags, among others. When trying to fix this I came up with a roundabout solution, before discovering that I didn’t need to, very similar to this solution for angularJS, most likely made before this was fixed (in around version 1.3).

In my case, I didn’t need the <base> tag at all – it was basically set as <base href=”/”>, most likely from the habit and all the examples and starter apps one uses to get their hands dirty with angular. All I needed to know about was APP_BASE_HREF. If you remove the <base> tag angular rightfully complains that it needs a base for its LocationStrategy to work, but APP_BASE_HREF enables us to set it from the bootstrap step:

import {
    APP_BASE_HREF
} from '@angular/common';

bootstrap(App, [
    ...{
        provide: APP_BASE_HREF,
        useValue: '/'
    }
]);

This works even for cases where the base isn’t ‘/’, so should be pretty much universal. Of course, if there are other reasons why you might need the base tag to stay in the page, the only solution is then to update the relevant properties so that their urls match the current one. I feel this should be avoided if at all possible, seeing as it isn’t the most clean or efficient method – not to mention that in our case, it would mean messing directly with the DOM on top of what an SVG animation library is already doing.

Nevertheless, here is an example of how that might look:

import {
    Directive,
    ElementRef,
    OnDestroy
} from '@angular/core';
import {
    Location
} from '@angular/common';

import $ = require('jquery');

@Directive({
    selector: '[update-clip-path]'
})
export class UpdateClipPath implements OnDestroy {
    private sub: any;

    constructor(private location: Location, private elementRef: ElementRef) {
        this.sub = this.location.subscribe(
            next => this.updateClipPath()
        );

        this.updateClipPath();
    }

    private updateClipPath() {
        if (this.elementRef.nativeElement) {
            $(this.elementRef.nativeElement)
                .find('[clip-path]')
                .each((index, el) => {
                    let clipPath = el.getAttribute('clip-path');
                    el.setAttribute(
                        'clip-path',
                        'url(' + this.location.path() + clipPath.substr(clipPath.indexOf('#')));
                });
        }
    }

    ngOnDestroy() {
        if (this.sub && this.sub.unsubscribe) {
            this.sub.unsubscribe();
        }
    }
}

Learning Javascript in a post-Reactive landscape

I recently re-watched a talk by Thomas Figg – Programming is terrible. In the QA portion of the talk there is a (perhaps surprisingly) positive tone in one of his answers – that learning to code is, contrary to what some might choose to believe, more accessible than ever. He then mentions JavaScript, as it is as simple as it is ubiquitous, and arguably the most easily shareable code in the world – everything from a TV to a phone will run it.

I completely agree with this statement, as JavaScript is at its core an incredibly simple language, in both theory and practice – both easy to reason about, and to get something running. But increasingly complex abstractions have become an integral part of any application development in JavaScript, making the entry barrier for a frontend developer higher and higher.

On Promises

Having worked as an AngularJS developer since it’s 0.x releases, I have more than gotten used to its $q library, modelled very closely after the Q library. They made sense to me, and any seasoned developer will most likely agree that they made asynchronous programming much easier to deal with.

Yet it wasn’t until joining a full stack team and getting tasked with tutoring my backend-heavy colleagues and QA’s on Promises that I noticed just how big of a stretch it can be if you’re facing these for the first time. They are not trivial, especially when you have to stray from the typical examples and delve into more complex usages.

On Reactive Programming

Reactive programming takes the concept of asynchronous programming further. Compared to promises, it is a step down the abstraction scale, making it easier to scale, to handle complex situations and concurrency with ease. Unfortunately, it also makes it much more complex conceptually – thus harder to get into and harder to reason about.

Angular2 fully supports and depends on RxJS, and although it is an “opt-in” kind of thing (just call .toPromise() on any Observable and it magically becomes just that), it is ubiquitous in the angular2 community. Go to any chatroom or forum and you see that you are expected to be comfortable with it.

A world of abstractions

AngularJS had a big problem – it looked easy, and it felt easy, until you tried doing anything complex with it. Angular 2 doesn’t make that mistake, showing its hand from the get-go. What this might mean for the community I don’t know – hopefully better code?

With Promises becoming a part of the ES6 standard, we are moving into a future where they become commonplace – jQuery 3 complies with Promises, for instance. The barrier to entry for developers gets forcefully higher at all levels.

As a teacher, you learn to avoid abstractions when teaching programming for the first time. An object-oriented language is not a good first language, for obvious reasons. I wonder if at some point, JavaScript will stop being one as well?

Angular2 router’s bumpy ride – a user’s perspective

Edit: ui-router is not mentioned at all in this article and should have been. This is only due to the fact that I haven’t worked with it enough to comment on it, and also because it is still in alpha, and not a popular ng2 router alternative in the community yet. That being said, it is the “only” router for me when in ng1-land, so I’m eager to give it a try, or see how much of it’s architecture influences Vladivostok.

Angular 2 is now in a release candidate state, after several beta releases, and while the core of this new iteration is an extremely solid one, many of its components are still under heavy development, which makes using them quite a bumpy ride.

The router component is perhaps the most notorious among them, with two iterations deprecated in the pace of a few short months – one officially so, and one never really seeing the light of day – and a third one on the way.

Now, it needs to be said that creating something like a router is far from trivial, particularly so if you are setting out to “revolutionise”, meaning solve all the known problems of previous routers. In the case of routing these are lazy loading, handling complex route structures, and enough flexibly to account for all use cases (with more or less legwork required).

Also, the reason why the angular team has gone through so many iterations has to do with how closely they are working with the community of users – the current iteration having taken a mere couple of months to get thrown out, so quick the community was to spot its shortcomings.

So, how do all of these routers differ, and where are they headed?

Enter @angular/router-deprecated

Angular2’s first stab at a router relied on the component paradigm heavily, as does angular2 in general. Components may have @RouteConfig annotations with route lists defined, and if they do, these get parsed and the relevant components loaded into a node in its template.

Most lifecycle hooks and checks could then be in the component itself, keeping thing neat and clean. This approach had a couple of problems:

  • As Routes were defined in the class file, deep linking to unloaded classes is impossible.
  • @CanActivate, which determines whether or not a certain route could be activated, had to be an annotation as it ran before the Component itself was instantiated.
  • Routes followed the same isolation pattern that Components did, but this meant not having access to the full route tree at any point, and having to hack your way around everything.

Enter @angular/router(-deprecated?)

The first attempt to solve these issues was promising:

  • It solved the deep linking problem by having routes be directly inferable from the url.
  • It intended to replace @CanActivate with CanActivateChild – it is now the parent’s task to determine if the route activation process can continue.
  • Access to the whole tree was given at any hooks

Unfortunately, it perpetuated some of the issues, like routes still defined as a Component’s annotation, and its development didn’t get very far before it getting scrapped – first unofficially and now officially so.

Enter @ngrx/router, and the “new new new Router”

If “new new new Router” seems like an atrocious expression it’s because it is – but it’s been a recurrent one in places like Gitter or Github issues. It is Vladivostok, and it’s approach is very similar to @ngrx/router (as its devs have been collaborating with the angular team closely).

@ngrx/router takes a cleaner, leaner and more low lever approach to routing:

  • Routes are defined as objects in their own right and injected into the app directly. Their loading becomes completely independent from the Components themselves.
  • A route has Guards that run whenever the route tree passes through it, these again completely independent from which Component is actually being loaded.
  • Changes in url that do not actually change routes, but only parameters (like changing from /user/1 to /user/2, for instance) do nothing by default – it is the user’s responsibility to listen to these changes and trigger behaviour
  • Routes, RouteParams, QueryParams, RouteData… All these are Observables that any Component can listen to – this makes it both more flexible and simpler, specially when creating something like a breadcrumb component, or anything more specific or unique.

A conclusion of sorts

Angular2 is heading in a really good direction, despite (or perhaps because of) all the growing pains it is going through. The downside of this is that it can’t live up to the extremely high expectations for everything from power to speed to ease of use, while in its betas and RCs.

The best way to get ready for the new router is to delve into @ngrx/router, which coincidentally is a pretty powerful tool in its own right. The documentation is sparse but its developers and users are quick to answer in their Gitter channel, and it is flexible enough to handle almost anything you’ll want to throw at it.

I’ll be throwing a couple of things myself, and write about that next.