Angular

Routing

Menu

Header

Footer

router-outlet

Application layout

Menu

Header

Footer

Nested views

Home

router-outlet

Routes structure

App

Root View

@RouteConfig(Route1, Route2)

Route 1

Route 2

Has children

@RouteConfig(Child1, Child2)

Child 1

Child 2

Getting started

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

@NgModule({
  imports: [ RouterModule.forRoot(appRoutes) ]
})
export class AppModule
const appRoutes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  { path: 'hero/:id',      component: HeroDetailComponent },
];

1. Import router module

2. Define routes

Routing Module

@NgModule({
  imports: [ AppRoutingModule ]
})
export class AppModule
import { NgModule } from '@angular/core';
// ...

const routes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  { path: 'hero/:id',      component: HeroDetailComponent },

];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Imports router module and defines routes

Usage

Router outlet

<header>
  <nav></nav>  
</header>
<main>
  <router-outlet></router-outlet>
</main>
<footer></footer>
<header>
  <nav></nav>  
</header>
<main>
  <app-page-one></app-page-one>
</main>
<footer></footer>

Page one

<header>
  <nav></nav>  
</header>
<main>
  <app-page-two></app-page-two>
</main>
<footer></footer>

Page two

app.component

Navigation

<nav>
  <a routerLink="/home" routerLinkActive="active">Home</a>
  <a routerLink="/me" routerLinkActive="active">My profile</a>
</nav>

With params

Simple

<nav>
  <a [routerLink]="['/user', userName]" routerLinkActive="active">My profile</a>
</nav>

http://localhost:4200/user/16387

http://localhost:4200/{home, me}

Navigation from components

Suitable for redirecting

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

@Component({ ... })
export class MyComponent {
  constructor(private router: Router) {}
}
public goToSecretPage() {
  this.router.navigate(['/secret']);
}
public goToSecretPage() {
  this.router.navigateByUrl('/secret');
}

Parsing route params

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

@Component({ ... })
export class MyComponent {
  public userName: string;

  constructor(public route: ActivatedRoute) {}
  // http://localhost:4200/user/:username
  ngOnInit() {
    this.userName = this.route.snapshot.params['userName'];
  }
}
import { ActivatedRoute } from '@angular/router';

@Component({ ... })
export class MyComponent {
  public userName: string;

  constructor(public route: ActivatedRoute) {}
  // http://localhost:4200/user/:username
  ngOnInit() {
    this.route.params.subscribe((params) => {
      this.userName = params.userName;
    });
  }
}

via subscription

Lazy loading

Designed for feature modules

Creating feature module

ng g module my-module --routing
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { MyRoutingModule } from './my-routing.module';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    MyRoutingModule
  ]
})
export class MyModule { }
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class MyModuleRoutingModule { }

Usage

const routes: Routes = [
  {
    path: 'lazy-loaded',
    loadChildren: () => import('./lazy-loaded/lazy-loaded.module')
    	.then(m => m.LazyLoadedModule)
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

Define nested routes (LazyLoadedRoutingModule)

const routes: Routes = [
  {
    path: '', // http://localhost:4200/lazy-loaded/
    component: PageOfLazyLoadedModule,
  },
  {
    path: 'info', // http://localhost:4200/lazy-loaded/info
    component: InfoPage,
  },
];

Guards

const canActivate: CanActivateFn =
  (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
    return inject(PermissionService).canActivate(UserToken, route.params['id']);
  };

const adminRoutes: Routes = [
  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [canActivate],
    children: [
      {
        path: '',
        children: [
          { path: 'crises', component: ManageCrisesComponent },
          { path: 'heroes', component: ManageHeroesComponent },
          { path: '', component: AdminDashboardComponent }
        ],
      }
    ]
  }
];

canActivate

interface UserToken {}

@Injectable({
  providedIn: 'root',
})
export class PermissionService {
  
  canActivate(currentUser: UserToken, userId: string): boolean {
    let url: string = state.url;

    return this.checkLogin(url);
  }

  checkLogin(url: string): boolean {
    if (this.authService.isLoggedIn) { return true; }

    // Store the attempted URL for redirecting
    this.authService.redirectUrl = url;

    // Navigate to the login page with extras
    this.router.navigate(['/login']);
    return false;
  }
}

Guard implementation

canMatch

for lazy-loaded modules

interface UserToken {}

@Injectable({
  providedIn: 'root',
})
export class PermissionService {

  canMatch(currentUser: UserToken): boolean {
  	let url = `/${route.path}`;

    return this.checkLogin(url);
  }

  checkLogin(url: string): boolean {
    // ...
  }
}
const canMatch: CanMatchFn = (route: Route, segments: UrlSegment[]) => {
  return inject(PermissionService).canMatch(UserToken);
};

const routes: Routes = [
  {
    path: 'lazy-loaded',
    loadChildren: './lazy-loaded/lazy-loaded.module#LazyLoadedModule',
    canMatch: [canMatch]
  }

Useful links

Thank you!

Angular. Routing

By Pavel Razuvalau

Angular. Routing

  • 911