A few weeks ago I wrote a post about how to create an inline spinner for your templates based on a loading state. While that’s still a viable solution, I ended up being my own devil’s advocate and building an alternative that I actually disagreed with at the time, and now find it to be the more favorable solution. I won’t say better, since both work and do different things. But in my application, the solution outlined in this post is the one I ultimately went with.

In this post, I’ll cover the componentized version of my spinner, which will allow you to use a spinner to block content from entering the DOM while its loading state is active, and then pass it through once the ready state has been activated. At the end of the day it’ll look like this:

<!-- your template -->
<div class='your-page'>
    <loading-indicator [loading]='loading'>

If you’re just here for the goods, you can get it on my GitHub.

Transclusion in Angular 2

What’s fun and ‘Angular’ about this approach is that it removes all the template logic for loading and displaying your spinner into a nice, packaged component that takes little-to-no effort to transport from one project to another. It does this by providing its own template, and then allowing the child elements in the parent template to pass through. In Angular 1.x, we would have called that transclusion. In Angular 2, it seems that name has died off, and these are just considered encapsulated views within the component’s rendered markup, instantiating the ViewEncapsulation class.

So how does that work? Angular provides a global directive, ng-content, that we can bake right into our Component template, which indicates to the browser that another template should be included in its place. In practice, that other template would be whatever child elements we add to the template where we use the parent component. For example, if we wanted to write a component that always wrapped its contents in a box, its class definition might look like this:

    selector: 'big-box',
    template: `
    <!-- I'm vehemently opposed to in-component styles; for demo purposes only -->
    <div style='border: 1px solid black; padding: 2em;'>
export class BoxBox {
    constructor() {}

And in order to use it, we’d add it to a template like so:

<div class='some-page'>
        <p>Think inside the box!</p>

If you want to learn more about view encapsulation in Angular 2, check out Todd Motto’s super-detailed explanation.

Creating a Loading Spinner Component

The goal is to create a component that will conditionally show a spinner when a page is loading, and alternatively allow the encapsulated view to enter the DOM when a page is done loading. Similarly to how I built the inline version in a previous post, I’m going to use the ngSwitch directive, which will allow me to block portions of my markup from entering the DOM based on the result of case evaluations. The template, as a result, looks like this:

    selector: 'loading-container',
    template: `
    <div [ngSwitch]="loading">
        <div *ngSwitchCase="false">
        <div *ngSwitchCase="true">
            <!-- markup for your spinner -->

You can use whatever markup or animated fanciness you want that works for your application visuals. For my simple implementation, I went with an SVG I got from this free SVG spinner site.

You’ll notice that we’re determining the state of the page based on a public property loading, which would ideally be a value passed in from whichever page uses this component. Therefore, we define it using the Input decorator:

export class LoadingContainer {
    @Input() loading: boolean;
    constructor() {}

Regarding dependencies, keep in mind that you’ll need the Input class, as well as a few directives; so you’ll have to import a few things to wire this up. Add these to the top of your file:

import {Component, Input} from 'angular2/core';

Not very complicated at all. So now that you have that going for you, you can drop it into whatever application page or component needs a spinner:

<ion-content class="login">
    <loading-container [loading]="loading">

Using a base page

In my previous post on this topic, I created a base LoadingPage class that looked like this:

export class LoadingPage {
    public loading: boolean;
    constructor(val: boolean) {
        this.loading = val;
    standby() {
        this.loading = true;
    ready() {
        this.loading = false;

When I need to implement a loading spinner, I can extend that class, and it will already have the properties I’m looking for in adding a loading condition that can be interpreted by my loading container:

// in my app, some Ionic imports...
import {LoadingContainer} from '../../components/loading-container';
import {LoadingPage} from '../../components/loading-page';

    template: `
            <ion-buttons end>
                <button ion-button (click)="navToRegister()">
                    Register &nbsp;<ion-icon name="person-add"></ion-icon>

    <ion-content class="login">
        <loading-container [loading]="loading">
export class LoginPage extends LoadingPage {
    public userEmail: string;
    public password: string;

    constructor(private _nav: NavController, private _user: UserService) {

    ionViewDidEnter() {
        this._user.determineUser().then((auth:AuthModel) => {
            if (auth) {
            } else {

    // more stuff...

Normally I’d put the template in a separate file, but for demonstration purposes this allows you to see what’s going on all at once.

Remember that this will need to be injected into your module’s declarations array in order to make it usable in your templates. For more information about that, check out the module API in the Angular documentation.

I’ve added another GitHub repo that includes both the LoadingPage class, and the LoadingContainer class in one file, so you can feel free to pull it into your project if you like. Any questions, feel free to reach out.

2 responses to “A Spinner Component Using View Encapsulation in Angular 2”

  1. Alex says:

    How to make it working on IE – it works on Chrome very well, but not on IE!

  2. Mike says:

    This is not a very good spinner component. What is being left out of this blog post is the the ng-content must be a component. It cannot simply be template html. Meaning, for this to work, there must exist both a LoginPage (describe above) and a LoginFormComponent (not included in this post).

    Having a spinner component that requires every page that uses it to abstract out all content into additional components is not very useful imho.

Leave a Reply

Your email address will not be published. Required fields are marked *