Skip to main content

Routing

Routing is a way to navigate between different components in an Angular application. It is done by using the RouterModule and Routes classes.

To add routing to an Angular application, you will need to:

  • create app-routing.module.ts
  • import AppRoutingModule in app.module.ts
  • import RouterOutlet in app module
const routes: Routes = [
{
path: 'first-route',
component: FirstComponentUsedInRoutingComponent,
},
{
path: 'second-route',
component: SecondComponentUsedInRoutingComponent,
},
];

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

Defining routes

Routes are defined by using the Routes class. Each route is defined by using the path and component properties. The path property is used to define the URL path, and the component property is used to define the component that will be displayed when the route is activated.

const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];

Displaying routes

To display routes, you need to add the element to the template of the component that will be used as the root component. This element will be replaced by the component that is defined in the route.

<router-outlet></router-outlet>

To navigate to a route, you need to use the routerLink directive. The routerLink directive is used to navigate to a route by using the path property of the route. For example, the following code navigates to the home route:

<a routerLink="/">Home</a>

To navigate to a new route from a component, you need to inject the Router service and use the navigate() method. For example, the following code navigates to the home route:

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

@Component({
selector: 'app-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss']
})
export class AboutComponent {
constructor(private router: Router) { }

navigateToHome() {
this.router.navigate(['/']);
}
}

Route parameters

Route parameters are used to pass data to a route. They are defined by using the path property of the route and are prefixed with a colon. For example, the following code defines a route with a parameter named id:

const routes: Routes = [
{ path: 'user/:id', component: UserComponent }
];

To access the route parameters, you need to inject the ActivatedRoute service and use the params property. For example, the following code accesses the id parameter:

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

@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.scss']
})
export class UserComponent {
id = '';

constructor(private route: ActivatedRoute) {
this.route.params.subscribe(params => {
this.id = params['id'];
});
}
}

You can also read the route parameters by using the snapshot property of the ActivatedRoute service. For example, the following code reads the id parameter:

export class UserComponent {
id = '';

constructor(private route: ActivatedRoute) {
this.id = this.route.snapshot.params['id'];
}
}
danger

The snapshot property of the ActivatedRoute service will not work if you navigate to the same route with different parameters. For example, if you navigate to the /user/1 route and then to the /user/2 route, the snapshot property will not work. To fix this, you need to subscribe to the params property of the ActivatedRoute service.

Styling active route

To style the active route, you need to use the routerLinkActive directive. The routerLinkActive directive is used to add a CSS class to an element when the route is active. For example, the following code adds the active class to the element when the route is active:

<a routerLink="/" routerLinkActive="active">Home</a>
danger

The routerLinkActive directive will mark as active all the routes that start with the path of the route. For example, if the path of the route is /user, then the routerLinkActive directive will mark as active all the routes that start with /user, such as /user/1, /user/2, etc. To avoid this, you can use the exact property of the routerLinkActive directive. For example, the following code will mark as active only the route that has the exact path:

<a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a>

Route guards

Route guards are used to prevent unauthorized access to routes. They are defined by using the canActivate property of the route. For example, the following code defines a route with a canActivate property:

const routes: Routes = [
{ path: 'user/:id', component: UserComponent, canActivate: [AuthGuard] }
];

Since Angular 16, canActivate will work functionally instead of with classes.

// Witout parameters

{
path: 'Dashboard',
canActivate: [() => inject(AuthGuard).canActivate()], // AuthGuard is your same class as it was before
component: DashboardComponent
}

// With parameters

{
path: 'Dashboard',
canActivate: [(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => inject(AuthGuard).canActivate(next, state)],
component: DashboardComponent
}

To create a route guard, you need to create a class that implements the CanActivate interface and define the canActivate() method. For example, the following code defines a route guard:

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

@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
canActivate() {
return // your activation logic goes here
}
}

Since angular 16 you should implement it like this:

@Injectable({
providedIn: 'root'
})
class PermissionsService {

constructor(private router: Router) {}

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return // your activation logic goes here
}
}

export const AuthGuard: CanActivateFn = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean => {
return inject(PermissionsService).canActivate(next, state);
}

Route resolvers

Route resolvers are used to load data before activating a route. They are defined by using the resolve property of the route. For example, the following code defines a route with a resolve property:

const routes: Routes = [
{ path: 'user/:id', component: UserComponent, resolve: { user: UserResolver } }
];

To create a route resolver, you need to create a class that implements the Resolve interface and define the resolve() method. For example, the following code defines a route resolver:

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

@Injectable({
providedIn: 'root'
})
export class UserResolver implements Resolve<any> {
resolve() {
return // your resolve logic goes here
}
}

Child routes (Nested routes)

Child routes are used to create routes that are children of other routes. They are defined by using the children property of the route. For example, the following code defines a route with a children property:

const routes: Routes = [
{
path: 'user/:id',
component: UserComponent,
children: [
{ path: 'profile', component: ProfileComponent },
{ path: 'settings', component: SettingsComponent }
]
}
];

To display child routes, you need to add the element to the template of the component that will be used as the parent component. This element will be replaced by the component that is defined in the child route.

<router-outlet></router-outlet>