Navigating A Web Application With The Angular Router

I’ve been keeping up with Angular since the beta releases and if you have too you’ll know that navigation has changed about one hundred times between then and the now stable release. Navigation with the Angular Router component is a tricky subject, but understanding it is necessary for pretty much every quality Angular web application.

I wrote a now obsolete tutorial on how to navigate between Angular routes back when Angular was in beta. Since Angular is now stable, I thought it would be a good idea to share how to navigate between pages with the stable Angular Router component.

To make this easy to understand, we’re going to focus on creating a multiple page Angular application based on the Angular CLI. If you don’t already have the Angular CLI, instructions on how to install it can be found here.

With the Angular CLI installed, execute the following from your Command Prompt (Windows) or Terminal (Mac and Linux):

ng new RouterProject

Navigate into the new project so we can continue to use the CLI to perform certain actions.

The next thing we want to do is generate two components that represent each of our two application pages. This can be done by executing the following from the Terminal or Command Prompt:

ng generate component page1 ng generate component page2

Executing the above commands will generate the appropriate HTML and TypeScript files. While Angular is in GA, as of right now the CLI is not. This means it is missing a few features that we’ll have to take care of manually.

Declaring the Application Routes and Components

Before we can navigate to these freshly created components we have to define them as navigation routes in our application. Create an app/app.routing.ts file in your project and include the following TypeScript code:

import { Page1Component } from './page1/page1.component'; import { Page2Component } from './page2/page2.component'; export const AppRoutes: any = [ { path: "", component: Page1Component }, { path: "page2", component: Page2Component } ]; export const AppComponents: any = [ Page1Component, Page2Component ];

In the above code we’re importing the two components and assigning them to a particular path. The default path, which is shown at application start, will have a blank path.

For code cleanliness we take all imported components and add them to an array to be included in the next step. We don’t have to do this, but it can easily get messy if we don’t.

Bringing the Routes Together via the NgModule

The routes are created, but they are not included in the application as a whole. Anything we want to include in the entire application is done in the @NgModule block of the project.

Open the project’s app/app.module.ts file and include the following TypeScript code:

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { RouterModule } from "@angular/router"; import { AppComponents, AppRoutes } from "./app.routing"; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent, ...AppComponents ], imports: [ BrowserModule, FormsModule, HttpModule, RouterModule, RouterModule.forRoot(AppRoutes) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Much of this file was created by the Angular CLI. However, notice in the declarations we’ve included ...AppComponents which was created previously in the app/app.routing.ts file. Remember how I said it could get messy if we didn’t add the components to an array? We could, if we wanted to, import and add each component here, but we chose not to.

Also take note of the imports and the following two lines:

RouterModule, RouterModule.forRoot(AppRoutes)

This is where we add the routes that we had defined.

Creating an Outlet for Displaying Route Components

The routes need to pass through something in the UI layer to become visible. If you’re familiar with AngularJS 1, you’ll be familiar with the HTML <div ui-view> tags. More information on AngularJS 1 routing can be found in a previous tutorial that I wrote.. It is very similar in Angular.

In the project’s app/app.component.html file, include the following code:

<h1>Welcome to the Router Example</h1> <router-outlet></router-outlet>

In Angular we use the <router-outlet> tags to accomplish this task. Nothing complicated, which is good for us.

Navigating Between the Application Pages with the Angular Router

The pages are now ready to go. Let’s build some very simple pages and check out how to navigate between them using the Angular Router component.

We’re going to start with the first page. Open the project’s app/page1/page1.component.ts file and include the following TypeScript code:

import { Component } from '@angular/core'; import { Router } from "@angular/router"; @Component({ selector: 'app-page1', templateUrl: './page1.component.html', styleUrls: ['./page1.component.css'] }) export class Page1Component { constructor(private router: Router) { } navigate() { this.router.navigate(["page2"]); } }

Take notice of the fact that we’re importing and injecting the Router and we’re also using it to navigate. Inside of the navigate method we attempt to navigate to page2 which is a path that we had defined in the app/app.routing.ts file. This isn’t the only way to navigate.

Let’s create the basic HTML and see how to navigate via HTML markup as well. Open the project’s app/page1/page1.component.html file and include the following markup:

<p>You're on the first page!</p> <p> <a (click)="navigate()">Navigate via TypeScript</a> | <a [routerLink]="['page2']">Navigate via Markup</a> </p>

Notice the use of the [routerLink] in the above markup. We’re able to use TypeScript or directives to accomplish the task of navigation.

With the first page out of the way, let’s have a look at the second page. Open the project’s app/page2/page2.component.ts file and include the following TypeScript code:

import { Component } from '@angular/core'; import { Location } from "@angular/common"; @Component({ selector: 'app-page2', templateUrl: './page2.component.html', styleUrls: ['./page2.component.css'] }) export class Page2Component { constructor(private location: Location) { } goBack() { this.location.back(); } }

In the above code we’re not including the Router. Instead we’re including Location which will allow us to navigate backwards in the navigation stack.

Open the project’s app/page2/page2.component.html file to add the matching HTML markup:

<p>You're on the second page!</p> <p> <a (click)="goBack()">Go Back via TypeScript</a> | <a [routerLink]="['/']">Go Back via Markup</a> </p>

Nothing too different from what we saw previously.

Conclusion

You just saw an up-to-date use of the Angular Router. While the previous tutorial I wrote has useful information, it doesn’t really help in terms of navigation in a stable-release Angular application.

There is a whole lot more you can do with navigation. For example you could also pass data between pages, but that is best explored in another tutorial.

Nic Raboy Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.