Show List
Angular Routing
The logic of defining the navigation elements and corresponding pages is called Routing. Angular provides RouterModule to help set up the routing.
Adding RouterModule
RouterModule can be added while creating a new Angular application or afterwards. While creating the new application using "ng new appName" command, Angular CLI prompts selection if you want to add RouterModule. If you chose "No" at that time, you can add RouterModule later using below command.
ng generate module app-routing --flat --module=app
- --flat flag puts the file in src/app instead of its own directory.
- --module=app flag tells ng generate to register it in the imports array of the AppModule
PS C:\Users\mail2\Downloads\angular\first-application> ng generate module app-routing --flat --module=app CREATE src/app/app-routing.module.ts (196 bytes) UPDATE src/app/app.module.ts (778 bytes)
app-routing.module.ts
Below is the default generated code
import { NgModule } from '@angular/core';import { CommonModule } from '@angular/common';@NgModule({declarations: [],imports: [CommonModule]})export class AppRoutingModule { }
Update it to below. We are using the two components home and pipedemo we created in the earlier tutorials for routing.
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { HomeComponent } from './home/home.component';import { PipedemoComponent } from './pipedemo/pipedemo.component';const routes: Routes = [{ path: '', component: HomeComponent },{ path: 'home', component: HomeComponent },{ path: 'pipedemo', component: PipedemoComponent }];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]})export class AppRoutingModule { }
app.module.ts
The RoutingModule gets registered in the app.module.ts as part of CLI command execution.
import { NgModule } from '@angular/core';import { FormsModule } from '@angular/forms';import { BrowserModule } from '@angular/platform-browser';import { AppComponent } from './app.component';import { HomeComponent } from './home/home.component';import { MyDirectiveDirective } from './my-directive.directive';import { PipedemoComponent } from './pipedemo/pipedemo.component';import { CuberootPipe } from './cuberoot.pipe';import { AppRoutingModule } from './app-routing.module';@NgModule({declarations: [AppComponent,HomeComponent,MyDirectiveDirective,PipedemoComponent,CuberootPipe],imports: [BrowserModule,FormsModule,AppRoutingModule],providers: [],bootstrap: [AppComponent]})export class AppModule { }
Accessing the Routes
From Browser URL
Directive "router-outlet" returns the component that gets matched based on the current browsers url. So after this directive is added on the root component html template, we can access the routes pages using the url.
app.component.html
<router-outlet></router-outlet>
Now, url "http://localhost:4200/" or "http://localhost:4200/home" would display the home component html.
Price Limit:
And url "http://localhost:4200/pipedemo" would display the pipedemo html.
4
Oct 16, 2022
Oct 16, 2022, 8:46:58 AM
8:46 AM
46:58
HELLO WORLD
hello world
Hello World
$123.25
0,003.14159
0,134.950%
{ "name": "Rob", "age": "35", "address": { "Line1": "100 First Steer", "Line2": "State K" } }
2,3
From HTML Template
Signature to access a route using anchor tag in HTML file:
<a routerLink="/home" routerLinkActive="active">First Component</a>
- routerLink sets the route to be called using the path.
- routerLinkActive sets the CSS class to be used when the route is activated.
home.component.html
Price Limit: <input type="text" [(ngModel)]="maxPrice"><br><br><button (click)="getProducts()"> Display Products </button><br><br><table class='table'><thead *ngIf="products.length > 0"><tr><th>ID</th><th>Name</th><th>Price</th></tr></thead><tbody><tr *ngFor="let product of products;"><ng-container *ngIf="product.price <= maxPrice"><td>{{product.productID}}</td><td>{{product.name}}</td><td>{{product.price}}</td></ng-container></tr></tbody></table><a routerLink = "/pipedemo" routerLinkActive="active">Navigate to pipedemo</a>
Home page now has a link to navigate to pipedemo page on click.
http://localhost:4200/home
From Within Component Class
To access routing from within the component class, we need to inject Router and ActivatedRoute. Navigation is then done using the syntax "this.router.navigate(['routeName'])"
home.component.ts
import { Component, OnInit } from '@angular/core';import { Product } from '../product';import { ProductService } from '../product.service';import { Router, ActivatedRoute } from '@angular/router';@Component({selector: 'app-home',templateUrl: './home.component.html',styleUrls: ['./home.component.css']})export class HomeComponent implements OnInit {products: any ;maxPrice:any;constructor(private ps:ProductService, private router: Router, private route: ActivatedRoute) { }ngOnInit(): void {}getProducts(){this.products = this.ps.getProducts;}goToPipeDemo(){this.router.navigate(['pipedemo']);}}
home.component.html
Price Limit: <input type="text" [(ngModel)]="maxPrice"><br><br><button (click)="getProducts()"> Display Products </button><br><br><table class='table'><thead *ngIf="products.length > 0"><tr><th>ID</th><th>Name</th><th>Price</th></tr></thead><tbody><tr *ngFor="let product of products;"><ng-container *ngIf="product.price <= maxPrice"><td>{{product.productID}}</td><td>{{product.name}}</td><td>{{product.price}}</td></ng-container></tr></tbody></table><a routerLink = "/pipedemo" routerLinkActive="active">Navigate to pipedemo</a><br><br><button (click)="goToPipeDemo()"> Go To Pipedemo </button>
Wildcard Route
Wild card route will match any route and is used to display error page when url path does not match any specified route.
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { ErrorpageComponent } from './errorpage/errorpage.component';import { HomeComponent } from './home/home.component';import { PipedemoComponent } from './pipedemo/pipedemo.component';const routes: Routes = [{ path: '', component: HomeComponent },{ path: 'home', component: HomeComponent },{ path: 'pipedemo', component: PipedemoComponent },{ path: '**', component: ErrorpageComponent }];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]})export class AppRoutingModule { }
Route Parameters
URL path parameters for the Route can be accessed either by using ParamMap observable or ActivatedRoute service.
ParamMap
It has following methods:
- has('parmName') − Returns true if the specified parameter is available in the path.
- get('parmName') − Returns the value of the specified parameter in the path.
- getAll('parmName') − Returns the multiple value of the specified parameter in the path.
- keys − Returns all parameter available in the path.
To access the path parameters, use paramMap in the ngOnInit of the component class.
pipedemo.component.ts
import { Component, OnInit } from '@angular/core';import { Router, ActivatedRoute } from '@angular/router';@Component({selector: 'app-pipedemo',templateUrl: './pipedemo.component.html',styleUrls: ['./pipedemo.component.css']})export class PipedemoComponent implements OnInit {idParm: any = null;dateProp: Date = new Date();stringProp: string = "Hello World";piProp: number = 3.14159265359;jsonProp: any = { name: 'Rob', age: '35', address: { Line1: '100 First Steer', Line2: 'State K' } };constructor(private router: Router, private route: ActivatedRoute) { }ngOnInit() {this.route.paramMap.subscribe(params => {this.idParm = params.get('id')});}}
pipedemo.component.html
<div *ngIf="idParm">ID {{idParm}} has been received</div><div *ngIf="!idParm">{{ 64 | cuberoot }}<br>{{ dateProp | date }}<br>{{ dateProp | date:'medium' }}<br>{{ dateProp | date:'shortTime' }}<br>{{ dateProp | date:'mm:ss' }}<br>{{ stringProp | uppercase }}<br>{{ stringProp | lowercase}}<br>{{ stringProp | titlecase}}<br>{{123.25 | currency:"USD"}}<br>{{piProp | number:'4.1-5'}}<br>{{1.3495 | percent:'4.3-5'}}<br>{{ jsonProp | json }}<br>{{[1,2,3,4,5,6,7] | slice:1:3 }}<br></div>
app-routing-module.ts
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { ErrorpageComponent } from './errorpage/errorpage.component';import { HomeComponent } from './home/home.component';import { PipedemoComponent } from './pipedemo/pipedemo.component';const routes: Routes = [{ path: '', component: HomeComponent },{ path: 'home', component: HomeComponent },{ path: 'pipedemo', component: PipedemoComponent },{ path: 'pipedemo/:id', component: PipedemoComponent },{ path: '**', component: ErrorpageComponent }];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]})export class AppRoutingModule { }
Navigating to url "http://localhost:4200/pipedemo/3" will show below text
ID 3 has been received
ActivatedRoute
ActivatedRoute interface provides information such as queryParams, params, url, data, component, firstChild, toString etc.
pipedemo.component.ts
import { Component, OnInit } from '@angular/core';import { Router, ActivatedRoute } from '@angular/router';@Component({selector: 'app-pipedemo',templateUrl: './pipedemo.component.html',styleUrls: ['./pipedemo.component.css']})export class PipedemoComponent implements OnInit {idParm: any = null;qryParm: any = null;dateProp: Date = new Date();stringProp: string = "Hello World";piProp: number = 3.14159265359;jsonProp: any = { name: 'Rob', age: '35', address: { Line1: '100 First Steer', Line2: 'State K' } };constructor(private router: Router, private route: ActivatedRoute) { }ngOnInit() {this.route.params.subscribe(params => {this.idParm = params['id']//console.log(this.idParm);});this.route.queryParams.subscribe(params => {this.qryParm = params['id']//console.log(this.qryParm);});}}
pipedemo.component.html
<div *ngIf="idParm">Path parameter id with value {{idParm}} has been received</div><div *ngIf="qryParm">Query parameter id with value {{qryParm}} has been received</div><div *ngIf="!idParm && !qryParm">{{ 64 | cuberoot }}<br>{{ dateProp | date }}<br>{{ dateProp | date:'medium' }}<br>{{ dateProp | date:'shortTime' }}<br>{{ dateProp | date:'mm:ss' }}<br>{{ stringProp | uppercase }}<br>{{ stringProp | lowercase}}<br>{{ stringProp | titlecase}}<br>{{123.25 | currency:"USD"}}<br>{{piProp | number:'4.1-5'}}<br>{{1.3495 | percent:'4.3-5'}}<br>{{ jsonProp | json }}<br>{{[1,2,3,4,5,6,7] | slice:1:3 }}<br></div>
app-routing-module.ts
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { ErrorpageComponent } from './errorpage/errorpage.component';import { HomeComponent } from './home/home.component';import { PipedemoComponent } from './pipedemo/pipedemo.component';const routes: Routes = [{ path: '', component: HomeComponent },{ path: 'home', component: HomeComponent },{ path: 'pipedemo', component: PipedemoComponent },{ path: 'pipedemo/:id', component: PipedemoComponent },{ path: '**', component: ErrorpageComponent }];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]})export class AppRoutingModule { }
Navigating to url "http://localhost:4200/pipedemo/3" will show below text
Path parameter id with value 3 has been received
Navigating to url "http://localhost:4200/pipedemo?id=4" will show below text
Query parameter id with value 4 has been received
Route Guards
Route Guards allow to run specific logic when a Route is requested. It is commonly used to check if the user is logged in and has the athorization. Here are some of the Route guard available:
- CanActivate - Used to control access to a Route
- CanActivateChild - To control access to a child Route
- CanDeactivate - Used to stop further processing based on the feedback from the user
- Resolve - To prefetch the data
- CanLoad - To control loading the assets
A Route Guard can be created from CLI using command "ng generate guard guardName". CLI will ask for the type of the guard.
PS C:\Users\mail2\Downloads\angular\first-application> ng generate guard rtguard ? Which interfaces would you like to implement? CanActivate CREATE src/app/rtguard.guard.spec.ts (346 bytes) CREATE src/app/rtguard.guard.ts (460 bytes)
rtguard.guard.ts
Below is the default code generated by the CLI. Logic can be added in the canActivate function to control the access.
import { Injectable } from '@angular/core';import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router';import { Observable } from 'rxjs';@Injectable({providedIn: 'root'})export class RtguardGuard implements CanActivate {canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {return true;}}
This guard can now be added to the route in the Routing Module.
app.routing.module.ts
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { ErrorpageComponent } from './errorpage/errorpage.component';import { HomeComponent } from './home/home.component';import { PipedemoComponent } from './pipedemo/pipedemo.component';import { RtguardGuard } from './rtguard.guard';const routes: Routes = [{ path: '', component: HomeComponent },{ path: 'home', canActivate: [RtguardGuard], component: HomeComponent },{ path: 'pipedemo', component: PipedemoComponent },{ path: 'pipedemo/:id', component: PipedemoComponent },{ path: '**', component: ErrorpageComponent }];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]})export class AppRoutingModule { }
Source Code:
https://github.com/it-code-lab/angular-application
Leave a Comment