Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Angular2 - Routing

4.55/5 (8 votes)
14 Jan 2017Apache4 min read 30.2K  
Routing in Angular2

What Is Routing?

Routing is a mechanism used by Angular for navigating between page and displaying appropriated component/page on browser.

I Was Confused, Can You Explain More in Detail?

OK, with our code, when you type on address bar, this URI "http://localhost/users".

Angular will look for the component (or web page) that will be rendered on browser based on information which was registered.

Which information do we need to register to Angular in order to view "http://localhost/users"?

Please check out the code from "https://github.com/techcoaching/angular2.git".

Open "<root>/src/userRoutes.ts", we see the code as below:

JavaScript
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { Users } from "./users";
import { CreateUser } from "./createUser";

let routes: Routes = [
    { path: 'users', component: Users },
    { path: 'createUser', component: CreateUser }
];
@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class UserRoutes { }

In this code, we register to Angular, When user accesses "<baseUrl>/users", Users component will be rendered on browser. baseUrl="http://localhost/" in this case.

JavaScript
{ path: 'users', component: Users },

On the browser, the content was rendered as photo below:

Image 1

I want the application redirects to "http://localhost/users" when user browses to "http://localhost", can I do that?

Yes, we can. Please add this route config into the list of route configurations:

JavaScript
{ path: "", redirectTo: "/users", pathMatch: 'full' }

userRoute.ts will be:

JavaScript
let routes: Routes = [
    { path: "", redirectTo: "/users", pathMatch: 'full' },
    { path: 'createUser', component: CreateUser },
    { path: 'users', component: Users }
    
];
@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class UserRoutes { }

When I run "http://localhost", the system redirects to "http://localhost/users", then I get "HTTP Error 404.0 - Not Found" when refreshing the browser, My app was deployed on IIS?

Yes, please help me to check if we have "web.config" file at root folder of the app. Missing this file will raise this type of error.

Image 2

Why do I need web.config file, I did not use any server code?

Browsing to "http://localhost/users" will trigger default handler on IIS and there is no content mapped to that URI. That is why the browser displays "HTTP Error 404.0 - Not Found"

XML
<rewrite>
	<rules>
		<rule name="Rewrite to default" enabled="true" stopProcessing="true">
			<match url="^[^.]+$" />
			<action type="Rewrite" url="/" />
		</rule>
	</rules>
</rewrite>

In Web.Config, it will auto rewrite the current request to "index.html" file (default page of IIS), this is where Angular handles the "/users" path using registered route configuration.

I got error as photo below when removing <base href="http://www.tranthanhtu.vn/"/> from index.html file, what is this?

Image 3

This is the HTML tag, for more information, see HTML <base> Tag.

In general, the browser uses this for identifying the location of resources that will be loaded.

By default, we use <base href="http://www.tranthanhtu.vn/"/>.

It seems the whole web-page was reloaded when I navigate between "Users" and "Add new User"?

Yes, look at layout.html, Link to "Users" and "Add new User" are pure HTML attributes.

Image 4

Please change them to:

Image 5

Now, let's try to click on these link again, the navigation between pages looks nicer.

Can I move the region of page content that will be displayed to other location?

In layout.html, we can move the "router-outlet" tag to the appropriate location.

Image 6

The content on browser will also be changed:

Image 7

Can I pass parameter from 1 page to another page and how can I do that?

Yes, you can. Let's add a new route config into UserRoutes.ts:

JavaScript
{ path: 'editUser/:id', component: CreateUser }

In constructor function of CreateUser:

JavaScript
export class EditUser{
    constructor(route: ActivatedRoute){
        console.log("User selected:", route.params.value.id);
    }
}

Instance of ActivatedRoute will be passed into the constructor of CreateUser by Angular using Dependency Inject (or DI in short) mechanism (We will talk about DI later).

We can get the value of passing parameter by: route.params["value"].<name of parameter in route config>. For example: route.params["value"].id will return id of selected user.

Image 8

How Can I Navigate Between Page From My Code?

Let add some HTML into users.html as below:

HTML
<div>
	<table class="table">
		<thead>
			<tr>
				<th>#</th>
				<th>First Name</th>
				<th>Last Name</th>
				<th>Username</th>
				<th>Action</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<th scope="row">1</th>
				<td>TU</td>
				<td>Tran</td>
				<td>@tutran</td>
				<td>
					<a (click)="onEditClicked(1)" title="Edit tutran">
                    <i class="fa fa-edit"></i></a>
				</td>
			</tr>
			<tr>
				<th scope="row">2</th>
				<td>TU</td>
				<td>Tran 1</td>
				<td>@tutran1</td>
				<td>
					<a (click)="onEditClicked(2)" title="Edit tutran1">
                    <i class="fa fa-edit"></i></a>
				</td>
			</tr>
			<tr>
				<th scope="row">3</th>
				<td>TU</td>
				<td>Tran 2</td>
				<td>@tutran2</td>
				<td>
					<a (click)="onEditClicked(3)" title="Edit tutran3">
                    <i class="fa fa-edit"></i></a>
				</td>
			</tr>
		</tbody>
	</table>
</div>

In Users class, we add "onEditClicked" handler as below:

JavaScript
import { Component } from "@angular/core";
import { Router } from "@angular/router";
@Component({
    selector: "users",
    templateUrl: "src/users.html"
})
export class Users {
    private router: Router;
    constructor(router: Router) {
        this.router = router;
    }
    public onEditClicked(userId: string) {
        this.router.navigate(["/editUser", userId])
    }
}

In the code, we use router.navigate function to navigate to "editUser" page:

JavaScript
this.router.navigate(["/editUser", userId])

Based on the route configuration in userRoutes.ts:

JavaScript
{ path: 'editUser/:id', component: EditUser }

What Can I Do if I Have More Than 1 Parameter?

we register route configuration:

JavaScript
{ path: 'editUser/:id1/:id2', component: EditUser }

And navigate using router.navigate function as below:

JavaScript
this.router.navigate(["/editUser", "value-of-id1", "value-of-id2"])

Can I Specify Optional Parameters in Route Configuration?

No at this time, all parameters are required. We can define multiple routes with different parameters as:
JavaScript
let routes: Routes = [
    { path: "", redirectTo: "/users", pathMatch: 'full' },
    { path: 'addNewUser', component: CreateUser },
    { path: 'editUser/:id', component: EditUser },
    { path: 'editUser/:id1/:id2', component: EditUser },
    { path: 'users', component: Users }
];

Using multiple routes with different parameters will create duplicated route configuration, is there any other solution for this?

I totally agree, this leads to many similar route configurations and raises other issues related to maintenance.

For optional parameters, we should pass them as query parameters. This is the correct use.

For example, in our case, id is a required parameter and id1 is optional. We only need to register route config for this as:

JavaScript
{ path: 'editUser/:id', component: EditUser }

userRoutes.ts will be:

JavaScript
let routes: Routes = [
    { path: "", redirectTo: "/users", pathMatch: 'full' },
    { path: 'addNewUser', component: CreateUser },
    { path: 'editUser/:id', component: EditUser },
    { path: 'users', component: Users }
];

In Users.ts, we navigate to "Edit User" page:

JavaScript
public onEditClicked(userId: string) {
	this.router.navigate(["/editUser", userId,{id1:"optional-parameter"}])
}

Note: Query parameters were passed as JSON object.

In EditUser.ts, we get back values of those and print to console:

JavaScript
export class EditUser{
    constructor(route: ActivatedRoute){
        let requiredIdparam=route.params["value"].id;
        let optionalIdparam=route.params["value"].id1;
        console.log("User selected:", requiredIdparam, optionalIdparam);
    }
}

The result in browser is as shown below:

Image 9

Thank for reading!

History

  • 14th Jan 2017: Initial version

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0