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:
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.
{ path: 'users', component: Users },
On the browser, the content was rendered as photo below:
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:
{ path: "", redirectTo: "/users", pathMatch: 'full' }
userRoute.ts will be:
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.
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
"
<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?
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.
Please change them to:
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.
The content on browser will also be changed:
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:
{ path: 'editUser/:id', component: CreateUser }
In constructor function of CreateUser
:
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.
How Can I Navigate Between Page From My Code?
Let add some HTML into users.html as below:
<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:
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:
this.router.navigate(["/editUser", userId])
Based on the route configuration in userRoutes.ts:
{ path: 'editUser/:id', component: EditUser }
What Can I Do if I Have More Than 1 Parameter?
we register route configuration:
{ path: 'editUser/:id1/:id2', component: EditUser }
And navigate using router.navigate
function as below:
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:
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:
{ path: 'editUser/:id', component: EditUser }
userRoutes.ts will be:
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:
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:
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:
Thank for reading!
History
- 14th Jan 2017: Initial version
CodeProject