Routing

  • Routing allows user to navigate to different part of application

  • It keeps your application linkable and bookmarkable

  • Allows you to maintain state of application

  • Allows to crate modular application ( every modules defies it's own route )

  • Allows to implement authoriation ( certain roles have access to certain urls )

Note

Routing is optional, we can build an application that never changes the url

Configuring Route

<head>
    <base href="/">
</head>
// routes.ts
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
    { path: 'home', component: "HomeComponent"},
    { path: 'about', component: "AboutComponent"}
];

export const routing = RouterModule.forRoot(routes);
  • path: URL to be shown in the browser when aplication is on specific route

  • component: Component displayed when user is on particular route

  • redirectTo: redirect route if needed

  • pathMatch: optional property to match full url or just the beggning

  • children: array of route definition object represting child routes

Using Router

import { routing } from './app.routes';

@NgModule({
    imports: [ BrowserModule, routing ],
    declarations: [ AppComponent, HomeComponent ],
    bootstrap: [ AppComponent ]
})
export class AppModule {}

Redirecting the router to another route

When your application starts, it navigates to empty route by default, we can configure router to redirect to a named route by default.

const routes: Routes = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: "HomeComponent"},
    { path: 'about', component: "AboutComponent"}
];
<a [routerLink]="/home">Home</a>
<router-outlet></router-outlet> <!-- route components added here -->

Alternatively you can navigate to route by calling navigate function on router

this.router.navigate(['/home']);

Route Parameter

const routes: Routes = [
    { path: 'product-detail/:id', component: "ProductDetailComponent" }
];

Access route parameter from component

ActivatedRoute service provides a params Observable which we can subscribe to get the route parameters.

import { ActivatedRoute } from '@angular/router';

@Component({})
export class ProductDetailComponent{
    constructor(private route: ActivatedRoute){ }
    ngOnInit(){
        this.routeSubscription = this.route.params.subscribe(params => {
            this.productId = +params['id'];
        });
    }

    ngOnDestroy(){
        this.routeSubscription.unsubscribe();
    }
}

Router trigger ( from HTML )

<a [routerLink]="['product-detail', productId]">
        {{ product.name }}
</a>

Child Routes

Specify child route by using the children route property

const routes: Routes = [
    { 
        path: 'product-detail/:id', 
        component: "ProductDetailComponent"
        children: [
            { path: '', redirectTo: 'overview', pathMatch: 'full' },
            { path: 'overview', component: OverviewComponent },
            { path: 'specs', component: SpecsComponent },
        ]
    }
];

This will create following API structure

product-detail/3/overview
product-detail/3/specs

Child route placeholder

Child route requires additional router-outlet just like we used in root application

@Component({
    selector: 'product-detail',
    template: `
        <h1>Product Detail: {{ productId }}</h1>
        <router-outlet></router-outlet> <!-- Overview & specs component get added here by router -->    
    `
})

Access parent route parameter from child router

export class Overview{
    constructor(private router: Router, route: ActivatedRoute){}
    ngOnInit(){
        this.subscription = this.router.routerState.parent(this.route)
                                                    .params.subscribe(params => {
                                                        this.parentProductId = this.params['id'];
                                                    })                                
    }
}

Passing query parameter

<a [routerLink]="['product-list']" [queryParams]="{page: 99 }">Go to page 99</a>

Alternatively we can navigate programmatically using Router service

goToPage(){
    this.router.navigate(['/product-list'], {queryParams: {page: 99 }});
}

Reading query parameters

import { ActivatedRoute } from '@angular/router';

@Component({})
export class ProductDetailComponent{
    constructor(private route: ActivatedRoute){ }
    ngOnInit(){
        this.routeSubscription = this.route.queryParams.subscribe(params => {
            this.page = +params['page'] || 0;
        });
    }
}

Protecting route with guards

  • CanActivate: gaurd navigation to a route

  • CanDeactivate: gaurd navigation from a route

  • Resolve: pre-fetch data before activating a route

  • CanLoad: Prevent asynchronous routing

Step 1- Create a Gaurd

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';


@Injectable()
export class ProductDetailGuard implements CanActivate{
    CanActivate(route: ActivatedRouteSnapshot): boolean{
        // route.url[1].path
    }
}

Step 2 - Registering a guard

import { ProductDetailGuard } from './products/product-guard.service';

@NgModule({
    providers: [ ProductDetailGuard ],
    bootstrap: [ AppComponent ]
})
export class AppModule{}

Step 3 - Using a guard

// routes.ts
const routes: Routes = [
    { 
        path: 'products/:id',
        canActivate: ProductDetailGuard,
        component: ProductDetailComponent
    },
    { 
        path: 'home',
        component: HomeComponent
    }
];

Last updated

Was this helpful?