A Fast Angular 2 Setup with Components and the Component Router

Angular 2 is nearing release candidate. I’m excited, and so are many others. Last week we spoke to Brad Green on our podcast where he uncovered some exciting aspects of Angular 2, as well as the future plans he has for building out awesome new features.

As we approach the first finish line for the release candidate, it’s time to start digging into the future of Angular. First up, Angular 2 is an entire rewrite of the first version that we know and love, usually referred to as “AngularJS”. There are common concepts between the two, however the architecture differs somewhat, as well as the way we write Angular code.

We’re going to build a really simple boilerplate, without compilers, tooling or other complexities and focus on fully understanding the architecture process behind setting up Angular 2 with components, TypeScript and routing. The source code will be available at the end!

Component Theory

To get absolutely anywhere with Angular 2, we need to first learn how to set it up for rendering components. Angular is all about components and component architecture – so essentially everything is a component, made up of other components!

This means we need a root component to serve as our application base, and then each other component we create will be some sort of child component thereafter.

Application structure

We’ll have a main file, called main.ts, which will take care of the bootstrapping and root component import. Each “view” we create will have it’s own file, such as home.component.ts, which is just a root component for the home view. This will then get hooked up to our router in which we can tell Angular where to display particular views. So let’s dig into the first step of setting up the HTML, importing the right libraries and then bootstrapping the application.

HTML setup

We’ll begin with an empty shell, and slowly assemble the bits we need. Here we have a basic HTML page:

<!doctype html>
<html>
  <head>
    <title>Superfast Angular 2 setup</title>
    <base href="/">
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>

  </body>
</html>

Next up, we’ll add the library dependencies we need from Angular 2 – note how we’re already including router.dev.js, which we’ll use later in this article! It’s an external module, so let’s add it after Angular 2.

<script src="/libs/angular2-polyfills.js"></script>
<script src="/libs/system.js"></script>
<script src="/libs/typescript.js"></script>
<script src="/libs/Rx.js"></script>
<script src="/libs/angular2.dev.js"></script>
<script src="/libs/router.dev.js"></script>

The second dependency we’ve added is system.js, which is a module loader. We’ll instruct it to tell Angular where our app is and to transpile our TypeScript:

<script>
System.config({
  transpiler: 'typescript',
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  map: {
    app: './js'
  },
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
System
  .import('app')
  .catch(console.error.bind(console));
</script>

Transpiling here will happen in the browser using typescript.js, which makes it so easy to get started without having to run local development servers and compiler tasks. For production we’ll obviously want to drop typescript.js and compile things locally, but for our simple getting-started project, it’s perfect!

What we’re doing is setting up system.js and pointing it to our app using map: {} and referencing our './js' directory. We then define the default extension (i.e. .ts) for TypeScript. Then, finally, we’re calling System.import() to dynamically fetch our application assets required to bootstrap our app. You can dive more into System.js here.

Bootstrapping

The bootstrap phase of an Angular 2 application is where we need to kickstart our app. We’ve already mentioned we’re going to be using main.ts for this, so let’s add some code and walk through it:

import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';

bootstrap(AppComponent);

For all Angular 2 development, we’re going to be using TypeScript, which means we get to use ES2015 import syntax. We need to import the bootstrap method using Object destructuring from 'angular2/platform/browser'. This makes it available within the file for calling as a function. On the second line, we add our AppComponent import, which we still need to create, so let’s get going with that!

Root App Component

Our root Component serves as the absolute base, and you could consider it to be “common” code shared across the entire application. For instance, it might contain a header with a logo, and possible sidebar with an area inside for managing views.

First we need to import Component from the Angular 2 core, and setup our class decorator with relevant metadata.

// app.component.ts
import {Component} from 'angular2/core';

@Component({
  selector: 'my-app',
  template: `
    <div class="app">
      Hello world!
      <main>
        <!-- stuff -->
      </main>
    </div>
  `
})
export class AppComponent {

}

The selector property in the @Component decorator refers to the custom element we’re going to need to create in our index.html file. So let’s jump over there and add the relevant tag:

<body>
  <my-app>
    Loading...
  </my-app>
</body>

We’ve added some text in the middle, Loading.... This gets displayed while the application is fetching the necessary assets. You could completely customize this contents with a unique loading bar or anything you like, and it’ll be replaced once Angular 2 is fully compiled and ready!

So far we’ve got the base of our app, with a single component. Ideally, we should now setup some Views and tie them into particular routes via the Component Router.

Views

With our bootstrap in order and root component rendered, it’s time to setup what we’d consider a view. A view is simply another component, but more of a high level one.

Let’s setup two views. Down the road, we create and import further components into our view, but, for purposes of this article and basic boilerplate, we’re simply going to be using high level view components and setting up routing.

Inside our app.component.ts, let’s add some imports for two views:

// app.component.ts
import {Home} from './home/home.component.ts';
import {Login} from './login/login.component.ts';

We’re creating two basic views here that are just Angular 2 components. Now that we’re referencing them, let’s create the files starting with our Home View Component:

// home/home.component.ts
import {Component} from 'angular2/core';

@Component({
  selector: 'home',
  template: `
    <h1>Home view!</h1>
  `
})
export class Home {
  constructor() {

  }
}

Then the Login view component:

/login/login.component.ts
import {Component} from 'angular2/core';

@Component({
  selector: 'login',
  template: `
    <h1>Login view!</h1>
  `
})
export class Login {
  constructor() {

  }
}

These are pretty much identical components, simply displaying a differnet view name inside an <h1> tag. Now taht we’ve got two views, we need to head back to main.ts and hook them up to the Component Router.

Routing

Angular 2’s component router is a simple decorator for a component class. Before we can use it, we need to import the ROUTER_PROVIDERS into our main.ts file and pass it into our bootstrap method as a custom provider. The bootstrap method takes an array of values:

// main.ts
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {ROUTER_PROVIDERS} from 'angular2/router';

bootstrap(AppComponent, [
  ROUTER_PROVIDERS
]);

Now the providers are added, we can then start using the router! Let’s dive back to app.component.ts and setup our router!

First, we need to import the router, namely the RouteConfig from the external angular2/router module:

// app.component.ts
...
import {RouteConfig} from 'angular2/router';

Next, we need to call the RouteConfig function. However, it’s a decorator, so we need to decorate the AppComponent class with it:

// app.component.ts
@RouteConfig([
  { path: '/', name: 'Home', component: Home, useAsDefault: true },
  { path: '/login', name: 'Login', component: Login }
])
export class AppComponent {

}

The above configuration defines the URL using path. The name of the Component allows us to alias the route so that we can dynamically link to the state inside our templates. The component property allows us to assign our Home or Login views respectively.

Let’s take a look at what we’ve got so far inside app.component.ts:

// app.component.ts
import {Component} from 'angular2/core';
import {RouteConfig} from 'angular2/router';
import {Home} from './home/home.component.ts';
import {Login} from './login/login.component.ts';

@Component({
  selector: 'my-app',
  template: `
    <div class="app">
      Hello world!
      <main>
        <!-- stuff -->
      </main>
    </div>
  `
})
@RouteConfig([
  { path: '/', name: 'Home', component: Home, useAsDefault: true },
  { path: '/login', name: 'Login', component: Login }
])
export class AppComponent {

}

Looking good! So we’ve completed the first step of telling Angular 2 what routes to setup, however we haven’t declared where our views will be dynamically rendered. We also have not created any sort of navigation between views with links.

Up top, we need to include ROUTER_DIRECTIVES. We can add it in nicely alongside RouteConfig:

// app.component.ts
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';

To be able to use ROUTER_DIRECTIVES, we need to pass it into our component!

// app.component.ts
@Component({
  selector: 'my-app',
  directives: [ROUTER_DIRECTIVES]
  template: `
    <div class="app">
      Hello world!
      <main>
        <!-- stuff -->
      </main>
    </div>
  `
})

Now that the directives from the component router module are available, we can specify where we want our views to be rendered. In Angular 2, these are called “route outlets.” There’s a <router-outlet> directive that we can use where we want these views to be rendered:

// app.component.ts
@Component({
  selector: 'my-app',
  directives: [ROUTER_DIRECTIVES]
  template: `
    <div class="app">
      Hello world!
      <main>
        <router-outlet></router-outlet>
      </main>
    </div>
  `
})

Angular will render our page out with the initial view as /, mount the component Home and render out <h1>Home view!</h1> inside our container. This is super!

So now we need to be able to let users navigate around our app using the routerLink property bindings. These bindings are also part of the ROUTER_DIRECTIVES and provide dynamic navigation based off the route name property:

// app.component.ts
@Component({
  selector: 'my-app',
  directives: [ROUTER_DIRECTIVES]
  template: `
    <div class="app">
      Hello world!
      <nav>
        <ul>
          <li>
            <a [routerLink]=" ['Home'] ">Home</a>
          </li>
          <li>
            <a [routerLink]=" ['Login'] ">Login</a>
          </li>
        </ul>
      </nav>
      <main>
        <router-outlet></router-outlet>
      </main>
    </div>
  `
})

We can pass in an array, which denotes the views associated with a routerLink. The first element in the array corresponds to a parent route, while child routes are specified as further array elements.

Conclusion

We’ve setup Angular 2 super fast, with some base components, routing and a bootstrap call, I’ve bundled this code on GitHub, you can grab it here and start playing! You will need to use a local server (of your chosing) to get it running, if you’re on OSX you can simply run python -m SimpleHTTPServer or use an IDE.

Comments

  • Pingback: Dew Drop – April 20, 2016 (#2234) | Morning Dew()

  • Nice explanation! A2 is starting to look interesting indeed. 😉

  • Josh Caplin

    Awesome article! You may want to clarify which (beta) version you’re using. One of the tough parts with finding good Angular2 references is that many are obsolete, and some don’t specify which alpha/beta version the syntax was meant to work with.

  • Gerard Sans

    Cool stuff!

  • A Developer Diary

    Nice tutorial, here is the steps to setup angular 2 development workspace easily using typescript.

    http://www.adeveloperdiary.com/angular-js/angular-2-x/setup-angular-2-typescript-development-workspace/

  • Rey David

    The code works great in the browser, Todd.
    < a [routerLink]=” [‘Login’] ” > Login < /a >
    However, when I run the same code on the Telerik AppBuilder platform for Android, it fails.
    It appears that the router link is resolving to something like: “file:///views/login.html”
    However, it appears that AppBuilder is expecting a path something more like: file:///data/data/com.telerik.Animegination/files/12590FAA-5EDD-4B12-856D-F52A0A1599F2/views/login.html
    I say this because that is what the path for my index.html file looks like.

    Is the Angular2 routerLink not supporeted in Telerik AppBuilder?
    How do I get this to work?

  • JimTheMan

    Nice article! I’m wondering though if it’s possible to send parameters to the new route via the [routerLink] syntax and also how to change routers this way from the typescript component files. 🙂

  • AngularVigilante

    Great stuff, but please update for the release version.

  • Sanjay kumar

    in current scenario, bootstrap(AppComponent); would be loaded every time when page loads. Would you please let us know the design which we can use for Angular2 and AEM. So that it loads only once with the clientlib.

  • Sanjay kumar

    I am trying to integrate Angular 2 with AEM. I am willing to bootstrap Angular 2 at page level so that I can wrap AEM page parsys inside Angular 2 root component. Any AEM component dragged inside page parsys would be a part of Angular 2 root component scope then. Any ideas how to achieve the same. I tried to include AEM page parsys inside typescript template section but it throws compile time error. Any help on this will be deeply appreciated.