In a Single Page Application, all your code exist in a single HTML page. When users access some specific features of the application, the browser will only render the parts that matter to the users instead of loading a new page. To define how users can navigate around our application, we can use routes. It provides us a mechanism to navigate from one part of our application to another. We can also configure routes to guard against unexpected behavior, authorize or pre-process some logic before loading the page.
If you remember, when we create a new Angular project via AngularCLI, it will ask us if we would like to add Angular routing or not. If we choose Yes, then it will create a file called app-routing.module.ts inside /app folder. In this file we can tell Angular which component should be displayed for a specific .
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
- path: specifies the URL segment or pattern associated with the route. It can be a static path like 'home', a parameterized path like 'product/:id', or a wildcard path like '*' for handling undefined routes.
- redirectTo: used to redirect a route to another one when the path matches instead of rendering a component.
- pathMatch: used in conjunction with redirectTo to define how the router should match and redirect routes. It can have two possible values: 'prefix' or 'full'. Default is 'prefix'.
- prefix: Angular will check the path from the left to see if the URL matches any given paths and stop when there is a match.
- full: Angular will check the entire URL with given paths. It is essential to do this when the we define an empty path, because empty string is a prefix of any URL.
- component: define which component will be loaded when the path matches.
- outlet: tell the name of a RouterOutlet where Angular can place our component into when the path matches.
- canActivate, canActivateChild, canDeactivate, resolve: an array of services which are used to attach route guards to specific routes or child routes. Route guards provide a way to control access to routes based on certain conditions. The canActivate guard determines if a route can be activated, canActivateChild is used for child routes, canDeactivate determines if a user can leave a route, and resolve is used to prefetch data before activating a route.
- data: Additional data developer want to provide to the component. Default, no data is passed.
- children: define an array of route objects that represent the child routes within a parent route.
- loadChildren: used to specify a module that need to be lazy loaded.
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home-component';
import { AboutComponent } from './about/about-component';
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
RouterOutlet is a directive exported by RouterModule. It is used to mark a place where the Angular router will render the component associated with the path we are at. We can have multiple outlets in our Angular application. The unnamed outlet will be the primary one, all the remaining outlets must have a name.
<router-outlet></router-outlet>
<router-outlet name="secondaryOutlet"></router-outlet>
RouterLink
When we work with html, we often do a navigation by passing the url to the href attribute of the a tag.
navbar.component.html
<a href="/home">Home</a>
<a href="/about">About</a>
navbar.component.html
<a routerLink="/home">Home</a>
<a [routerLink]="['/about']">About</a>
navbar.component.html
<button (click)="routeToHomePage()"></button>
navbar.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
})
export class NavbarComponent implements OnInit {
constructor(private router: Router) { }
ngOnInit(): void {
}
routeToHomePage() {
this.router.navigate(['/home'])
}
}
- CanActivate: This guard determines if a route can be activated or not. It is used to check if a user has the necessary permissions or authentication to access a specific route. If the guard returns true, the navigation is allowed, but if it returns false or a Promise/Observable that resolves to false, the navigation is blocked.
- CanActivateChild: This guard is similar to CanActivate but specifically applies to child routes. It is used to control access to child routes of a parent route.
- CanDeactivate: This guard is used to determine if a user can leave a route or component. It is commonly used to prompt the user with a confirmation dialog when they try to navigate away from a form or unsaved changes.
auth.guard.ts
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
UrlTree,
Router
} from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
if (this.authService.isAuthenticated()) {
return true;
} else {
// Redirect to login page if not authenticated
this.router.navigate(['/login']);
}
}
}
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home-component';
import { AboutComponent } from './about/about-component';
import { LoginComponent } from './login/login-component';
import { AuthGuard } from './auth/auth.guard'
const routes: Routes = [
{ path: 'home', component: HomeComponent, canActivate: [AuthGuard]},
{ path: 'about', component: AboutComponent },
{ path: 'login', component: LoginComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }