Support us .Net Basics C# SQL ASP.NET ADO.NET MVC Slides C# Programs Subscribe Buy DVD

Angular 2 routing tutorial

Suggested Videos
Part 27 - Angular 2 http service tutorial | Text | Slides
Part 28 - Angular 2 http error handling | Text | Slides
Part 29 - Using Bootstrap with Angular 2 | Text | Slides

In this video we will discuss the basics of routing in Angular 2. Routing allows users to navigate from one view to another view.

At the moment, we have EmployeeListComponent in our application. Let's create another simple HomeComponent so we can see how to navigate from HomeComponent to EmployeeListComponent and vice-versa



Creating HomeComponent
1. Right click on the "app" folder and add a new folder. Name it "home". Right click on the "home" folder and add a new TypeScript file. Name it home.component.ts. Copy and paste the following code in it. Notice we have not included the 'selector' property in the @component decorator. The selector is only required if we are going to embed this component inside another component using the selector as a directive. Instead we are going to use the router to navigate to this component.



import { Component } from '@angular/core';

@Component({
    template: '<h1>This is the home page</h1>'
})
export class HomeComponent {
}

2. In the application root module (app.module.ts) import HomeComponent and include it in the declarations array of @NgModule decorator.

import { HomeComponent } from './home/home.component';

@NgModule({
    imports: [BrowserModule, FormsModule, HttpModule],
    declarations: [AppComponent, HomeComponent, ...],
    bootstrap: [AppComponent]
})

export class AppModule { }

If the user tries to navigate to a route that does not exist, we want to route the user to PageNotFoundComponent. So let's create this component as well.

Right click on the "others" folder and add a new TypeScript file. Name it pageNotFound.component.ts. Copy and paste the following code in it.

import { Component } from '@angular/core';

@Component({
    template: '<h1>The page you are looking for does not exist</h1>'
})
export class PageNotFoundComponent {
}

Next, in the application root module (app.module.ts) import PageNotFoundComponent and include it in the declarations array of @NgModule decorator.

import { PageNotFoundComponent } from './Others/pageNotFound.component';

@NgModule({
    imports: [BrowserModule, FormsModule, HttpModule],
    declarations: [AppComponent, PageNotFoundComponent, ...],
    bootstrap: [AppComponent]
})
export class AppModule { }

Here are the steps to implement routing in Angular 2 applications.

Step 1 : Set <base href> in the application host page which is index.html. The <base href> tells the angular router how to compose navigation URLs.

<base href="/src/">

Step 2 : In our angular application root module (app.module.ts), import RouterModule and Routes array and define routes as shown below.

import { RouterModule, Routes } from '@angular/router';

// Routes is an array of Route objects
// Each route maps a URL path to a component
// The 3rd route specifies the route to redirect to if the path
// is empty. In our case we are redirecting to /home
// The 4th route (**) is the wildcard route. This route is used
// if the requested URL doesn't match any other routes already defined
const appRoutes: Routes = [
    { path: 'home', component: HomeComponent },
    { path: 'employees', component: EmployeeListComponent },
    { path: '', redirectTo: '/home', pathMatch: 'full' },
    { path: '**', component: PageNotFoundComponent }
];

// To let the router know about the routes defined above,
// pass "appRoutes" constant to forRoot(appRoutes) method
@NgModule({
    imports: [
        BrowserModule, FormsModule, HttpModule,
        RouterModule.forRoot(appRoutes)
    ],
    declarations: [AppComponent, HomeComponent, …],
    bootstrap: [AppComponent]
})
export class AppModule { }

Important: The order of the routes is very important. When matching routes, Angular router uses first-match wins strategy. So more specific routes should be placed above less specific routes. In the configuration above, routes with a static path are listed first, followed by an empty path route, that matches the default route. The wildcard route comes last because it matches every URL and should be selected only if no other routes are matched first.

Step 3 : Tie the routes to application menu. Modify the root component (app.component.ts) as shown below. The only change we made is in the inline template.
  • We are using Bootstrap nav component to create the menu. We discussed Bootstrap nav component in Part 27 of Bootstrap tutorial.
  • The routerLink directive tells the router where to navigate when the user clicks the link.
  • The routerLinkActive directive is used to add the active bootstrap class to the HTML navigation element whose route matches the active route.
  • The router-outlet directive is used to specify the location where we want the routed component's view template to be displayed.
  • The routerLink, routerLinkActive and router-outlet directives are provided by the RouterModule which we have imported in our application root module.
  • If you forget to specify the router-outlet directive, you will get and error stating - cannot find primary outlet to load component.
import { Component } from '@angular/core';

@Component({
    selector: 'my-app',
    template: `
                    <div style="padding:5px">
                        <ul class="nav nav-tabs">
                            <li routerLinkActive="active">
                                <a routerLink="home">Home</a>
                            </li>
                            <li routerLinkActive="active">
                                <a routerLink="employees">Employees</a>
                            </li>
                        </ul>
                        <br/>
                        <router-outlet></router-outlet>
                    </div>
              `
})
export class AppComponent {
}

Step 4 : Finally in web.config file of our angular application include the following url-rewrite rule to tell IIS how to handle routes. The match url, <match url=".*" />, will rewrite every request. The URL in <action type="Rewrite" url="/src/"/> should match the base href in index.html.

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Angular Routes" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/src/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

If you do not have the above url rewrite rule, when you referesh the page you will 404 page not found error.

To use "hash style" urls instead of HTML5 style url's, you just need to make one change in app.module.ts file. Set useHash property to true and pass it to the forRoot() method as shown below.

RouterModule.forRoot(appRoutes, { useHash: true })

If you are using "hash style" routes, we don't need the URL rewrite rule in web.config file.

Angular 2 tutorial for beginners

12 comments:

  1. Hi sir
    Some times my routing is not working if i refresh the browser or press the link button
    Page is showing Empty and in Firebug Console angular module are not loaded
    if am clicking multiple times on the menu, then its load

    ReplyDelete
  2. Perfect.. Thanks Venkat for such great and spontaneous efforts. Appreciated!!!

    ReplyDelete
  3. Nice explanation, some how Home and Employee is displayed as bullets, not as Tabs showed in the demo. Could you please help why ?
    Rest of the functionality is working.

    ReplyDelete
    Replies
    1. I think you missed bootstrap reference in your main file ... or a wrong reference ...

      Delete
  4. Dear venkat, great article. I have installed bootstrap & jQuery using npm console. i did add bootstrap.css, jQuery.min.js to index.html page. but when i execute my application, home and employee are displayed as un-ordered list my url - http://localhost:***7/src/home. when i edit url http://localhost:***7/ removing 'home' then it does bind with bootstrap. May i know y my application isn't binding at first time. Thanks again.

    ReplyDelete
  5. sir when i navigate to the employee list page then the routing is not works properly. the error message shows that
    ERROR Error: Uncaught (in promise): TypeError: this._unsubscribeAndRecycle is not a function
    TypeError: this._unsubscribeAndRecycle is not a function
    at CatchSubscriber.error (catch.ts:110)
    at Observable.eval [as _subscribe] (apply_redirects.ts:64)
    at Observable.subscribe (Observable.ts:77)
    at CatchOperator.call (catch.ts:80)
    at Observable.subscribe (Observable.ts:77)
    at Object.subscribeToResult (subscribeToResult.ts:33)
    at MergeMapSubscriber._innerSub (mergeMap.ts:138)
    at MergeMapSubscriber._tryNext (mergeMap.ts:134)
    at MergeMapSubscriber._next (mergeMap.ts:118)
    at MergeMapSubscriber.Subscriber.next (Subscriber.ts:95)
    at CatchSubscriber.error (catch.ts:110)
    at Observable.eval [as _subscribe] (apply_redirects.ts:64)
    at Observable.subscribe (Observable.ts:77)
    at CatchOperator.call (catch.ts:80)
    at Observable.subscribe (Observable.ts:77)
    at Object.subscribeToResult (subscribeToResult.ts:33)
    at MergeMapSubscriber._innerSub (mergeMap.ts:138)
    at MergeMapSubscriber._tryNext (mergeMap.ts:134)
    at MergeMapSubscriber._next (mergeMap.ts:118)
    at MergeMapSubscriber.Subscriber.next (Subscriber.ts:95)
    at resolvePromise (zone.js:814)
    at resolvePromise (zone.js:771)
    at zone.js:873
    at ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (ng_zone.ts:288)
    at ZoneDelegate.invokeTask (zone.js:420)
    at Zone.runTask (zone.js:188)
    at drainMicroTaskQueue (zone.js:595)
    at ZoneTask.invokeTask [as invoke] (zone.js:500)
    at invokeTask (zone.js:1540)
    One more point i noted that when i defines the route error in app module file when we set the employeelist component path on first and the specify the home page path then empoyee list page load data but home page link gives the same error. please tell me what could be the problem with that.

    ReplyDelete
  6. Dear Venkat and Friends... Am getting the below errors. Tried many ways ..but in vain. Plz help.










    Error: (SystemJS) Unexpected token <
    SyntaxError: Unexpected token <
    at eval ()
    at Object.eval (http://localhost:52866/src/app/employee/employee.service.js:17:1)
    at eval (http://localhost:52866/src/app/employee/employee.service.js:39:4)
    at eval (http://localhost:52866/src/app/employee/employee.service.js:40:3)
    Evaluating http://localhost:52866/node_modules/rxjs/add/operator/throw.js
    Evaluating http://localhost:52866/src/app/employee/employee.service.js
    Evaluating http://localhost:52866/src/app/employee/employeeList.component.js
    Evaluating http://localhost:52866/src/app/app.module.js
    Evaluating http://localhost:52866/src/main.js
    Error loading http://localhost:52866/src/main.js
    at eval ()
    at Object.eval (http://localhost:52866/src/app/employee/employee.service.js:17:1)
    at eval (http://localhost:52866/src/app/employee/employee.service.js:39:4)
    at eval (http://localhost:52866/src/app/employee/employee.service.js:40:3)
    Evaluating http://localhost:52866/node_modules/rxjs/add/operator/throw.js
    Evaluating http://localhost:52866/src/app/employee/employee.service.js
    Evaluating http://localhost:52866/src/app/employee/employeeList.component.js
    Evaluating http://localhost:52866/src/app/app.module.js
    Evaluating http://localhost:52866/src/main.js
    Error loading http://localhost:52866/src/main.js

    ReplyDelete
    Replies
    1. I'm also getting the same error. Were you able to fix this Srikanth?

      Delete
    2. I was getting the same error. After struggling for couple of hours, i found that it was copy paste error. In my project's service typescript file, I had
      import 'rxjs/add/operator/throw';
      instead of
      import 'rxjs/add/observable/throw';

      After correcting this copy paste mistake, the application started running.

      Delete
  7. i am getting below errors
    could you pleasse help me how to resolve these errors

    "Uncaught SyntaxError: Unexpected token <" in below files


    shim.min.js,zone.js ,system.src.js,jquery.min.js,bootstrap.min.js,system.js,systemjs.config.js



    Uncaught ReferenceError: System is not defined
    at index.html:22

    " System.import('main.js').catch(function(err){ console.error(err); });"

    ReplyDelete
  8. Hi Kuduvenkat,

    First of all thanks for putting all these articles out there. It is the simplest tutorial I could find and been following it for some time.

    Can you also add how to make multiple routes work in the same application? while doing the examples, I created the components as a Module and once this step was over I copied all the files from HomeComponent to create a new module. I updated the names to load them and the new module is working fine except routing. for routed pages, still the old pages are showing up. I changed the names [path: 'home', component: home.HomePageComponent ] to [path: 'homeParam', component: home.HomePageComponent], but now it is showing page not found.

    what is wrong with what I am doing? Can you add some directions and samples on how to implement nested routes / localized routes in Angular to this Page? I guess that got some additional steps to make it work.

    ReplyDelete

If you like this website, please share with your friends on facebook and Google+ and recommend us on google using the g+1 button on the top right hand corner.