In this tutorial you will learn Angular 2 Routing from scratch by buildng a real life application . The Angular 2 router was built with componentization in mind. We will see how can we create our custom links and make components react to them in the following pages. In this Tutorial, we will:

  • Discover how to define routes to switch components on and off and redirect them to other routes
  • Trigger routes and load components in our views depending on the requested route
  • Pass parameters to our components straight from our routes
  • Look at the different component lifecycle hooks based on the routing stages
  • Define different URL representation strategies

Adding support for the Angular 2 router

Angular team introduced a revamped routing mechanism when switching versions from Beta to Release Candidate. This new routing machinery, which aims to replace the routing API that Angular had been implementing since its Alpha version, also introduced relevant breaking changes with its previous incarnation. In order to ensure that applications built on top of the previous router could upgrade to Angular 2 Release Candidate seamlessly and prevent major issues, the Angular team made available a snapshot of the Beta Router, available from the @angular/router-deprecated barrel. That is why we installed and configured two routing packages.

We also need to inform Angular about the base path we want to use, so it can properly build and recognize the URLs as the user browses the website, as we will see in the next section. Our first task will be to insert a base href statement within our <HEAD> element. Append the following line of code at the end of your code statement inside the <head> tag:

index.html

<base href="/">

The base tag informs the browser about the path it should follow while attempting to load external resources, such as media or CSS files, once it goes deeper into the URL hierarchy.

Now, we can start playing around with all the goodies existing in the router library. Prior to this, we would need to inform the dependency injector about how it can instantiate the tokens we will require later on while implementing the routing features in our components. All these providers are accessible from the ROUTER_PROVIDERS symbol. In a similar fashion as we did with HTTP_PROVIDERS, we need to declare it in the providers property of the top root component so that it is available for all its child components’ injectors.

Open your top component module and append the following import statement to the existing block of imported symbols. Then, add it to the providers property of the component decorator:

app/app.component.ts

...
import { SHARED_PROVIDERS } from './shared/shared';
import { HTTP_PROVIDERS } from '@angular/http';
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';

@Component({
  selector: 'pomodoro-app',
  directives: [ROUTER_DIRECTIVES],
  providers: [SHARED_PROVIDERS, HTTP_PROVIDERS, ROUTER_PROVIDERS],
  template: `
...

Setting up the router service

With the providers and directives in place, our first step will be to turn our main host component into a router component. Basically, any component can become a routing component just by conforming to the following requirements:

  • Just like the component class is flagged with a @Component decorator, we want to decorate it with a @RouteConfig decorator.
  • The @RouteConfig decorator is configured with an array of RouteDefinitions, which are basically object literals defining a path identified with a name and pointing to a component type.
  • The component decorated with the @RouteConfig decorator is then supposed to include a RouterOutlet directive in its template. This element will become the placeholder where the components will be loaded and rendered upon loading a route pointing to each of them, removing any previous component existing there, if any.

In this sense, it is right to say that the router watches for state changes in the browser URL and then searches for a RouteDefinition object whose path property matches the existing URL. Then, it instantiates the component defined in such route definition inside the placeholder represented by the router outlet directive, which is meant to live in the template belonging to the component decorated with that router configuration.

Let’s see all this through a real example. we will define different routes to use each one, implementing the following logic:

  • The user reaches our app and checks the current listing of the tasks pending to be done. The user can schedule the tasks to be done in order to get the required time estimation for the next Pomodoro session.
  • If desired, the user can jump onto another page and see a create task form (we will create the form, but will not implement its editing features until the next chapter).
  • The user can choose any task at any time and begin the Pomodoro session required to accomplish it.
  • The user can move back and forth across the pages she or he has already visited.