TU Tran

Technologies should serve for business purpose.

NAVIGATION - SEARCH

Angular2 - Routing

What is routing?

Routing is 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) 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 checkout the code from "https://github.com/techcoaching/angular2.git" in "feature/angular2-routing" branch.

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 access to "<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 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 got "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 not content mapped to that URI. That is why the browser display "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="/"/>  from index.html file, what is this?

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

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

By default we use <base href="/"/>

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 try to click on these link again, the navigation between pages looks nicer.

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

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

The content on browser will be changed also:

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

Yes, You can. Let add 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])

Base 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 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 as below:

Where can I find more articles in Angular2 series?

For learning Angular2, I think you should follow the list of articles as below (click on link to see detail page):

  • Overview: Introduce about Angular2
  • Routing: Understand how Angular2 navigate between pages/ components
  • Component: Learn about components/ pages in Angular2.
  • Binding: Learn how Angular2 show data on UI and receive input data from user.
  • Directive: Learn how to create re-usable component/ control that can be re-used across the application.
  • Integrate together: using what we learn about Angular for building the sample demo. 
  • Append "angular 2" into current "Angular 1" application.

 

Thank for reading.

Note: Please like and share to your friends if you think this is usefull article, I really appreciate

Comments (5) -

I have a question to your routing article: Is it possible to let PHP take the /Users route and then load the whole Angular needed stack again in this completely different page?

I am asking because I have a huge traditionally PHP project setup and I need angular just to handle the events in buttons and for doing some Ajax requests. Frontend form validation is also a nice feature, which I plan to use. But that's it. I don't need angular to control the whole application. So is it possible with that routing to escape that SPA hell?

Reply

Hi Thomas,
Thank for sending me your question.
I'm not strong in PHP. Idealy, we can do it.
As I understand your quesiton, we expect to load angular in specified page only and perform a limitted action on that page.
The solution is:
- Navigate to "/users" URI, let your PHP handle and load appropriated page (assume it is users.php).
- Copy index.html in my code to this user.php page.
The agular will beloaded into users.php page. Then we can use it as we need.

From your explaination, I think you should not use angular for this. There are others lighweigh for this. Such as JQuery is an sample. You can look at http://api.jquery.com/jquery.ajax/

Hope this can help you solving you problem.
Regards,
TU Tran

Reply

Yeah, thanks. I would like to refactor my project from jQuery to a modern JavaScript library. For now I am thinking of maybe VueJS, but it has only native TypeScript support. Or also maybe ExtJS or EmberJS. These are the only librariers, that let us the freedom to structure our code how we want and not how the library tells us.

Reply

Hi Thomas,
I think it is nice to refactor the code to use more advance library.
But we need to consider the scope of work we want to have after reafctoring.
If you want to have a SPA for improving your user interation. I will say Yes on using angular. ExtJS, Ember, ... as this is the target for those frameworks.
Otherwise, if we only need to improve the communication (from posting to ajax, or something like that). I suggest that we should not use.
As we just use a small part of that framework
As mmindset, I usually determine what do I want first base on my business logic and select the techs (framework, library, ...) that best fit to my purpose. it will be better.
Hope this can help you on deciding what will you don with your project.

Regards,
TU Tran

Reply

really good publish, i undoubtedly enjoy this internet web site, carry on it

Reply

Add comment