The most basic and common in almost every web, mobile, or responsive web application feature are routing and navigation. Angular uses a single-page application which means navigating between views, screens or contents does not need to change the whole page. Angular Router is used to navigate between views. When the user clicks the link that will change the URL then the Angular Router will interpret it as an action to switch or change to another view.
Table of Contents:
- Preparation
- Basic Route Example
- Route Information Example
- Wildcard Routes Example
- Nesting Routes Example
- Custom Route Animation Example
In this tutorial, we will create a new Angular application with a routing module as default. Then continue with more views and nested views completed with send/get params, animated transitions, child routing, etc.
You can watch the video tutorial on our YouTube channel here.
Preparation
We assume that you have installed Node with NPM or Yarn. To make sure all is installed, open the terminal and then type this command.
node -v
v18.14.0
npm -v
9.3.1
yarn --version
1.22.19
The Node.js and NPM versions that we use are the stable and recommended version. In Windows Power Shells, type this command to enable the execution of PowerShell scripts.
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
Next, we have to install Angular CLI by typing this command.
npm install -g @angular/cli
Now, we have the latest version of Angular when this example was written.
ng version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 15.1.6
Node: 18.14.0
Package Manager: npm 9.5.0
OS: win32 x64
Angular:
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.1501.6 (cli-only)
@angular-devkit/core 15.1.6 (cli-only)
@angular-devkit/schematics 15.1.6 (cli-only)
@schematics/angular 15.1.6 (cli-only)
Next, create an Angular 13 application for this Routing & Navigation example by typing this command.
ng new routing-sample --routing --defaults
Next, to sanitize the newly created Angular project go to that project folder then run the Angular application.
cd routing-sample
ng serve
You will this page or view it when you open http://localhost:4200/ in your browser which means the Angular is ready to go.
Now, this Angular application is ready to use with the routing and navigation examples. To close the running Angular application just press CTRL+C.
Basic Route Example
Before creating a basic route, first, we need to add a new Angular component by typing these commands.
ng generate component bedroom
ng generate component bathroom
Those newly generated components will automatically register in the src/app/app.module.ts. So, we just need to add them to the src/app/app-routing.module.ts. Open that file then add these imports.
import { BedroomComponent } from './bedroom/bedroom.component';
import { BathroomComponent } from './bathroom/bathroom.component';
Next, add or modify the constant variable of routes by this array of component routes.
const routes: Routes = [
{ path: 'bedroom', component: BedroomComponent },
{ path: 'bathroom', component: BathroomComponent },
];
Those components in the Routes variable are accessible through these URLs.
http://localhost:4200/bedroom -> navigate to BedroomComponent
http://localhost:4200/bathroom -> navigate to BathroomComponent
Next, we will navigate to those each component by adding these Hyperlinks inside the main Angular component. Open and edit src/app/app.component.html then replace all HTML tags inside the <div> with class name content.
<div class="content" role="main">
<ul>
<li><a routerLink="/bedroom" routerLinkActive="active">Bedroom Component</a></li>
<li><a routerLink="/bathroom" routerLinkActive="active">Bathroom Component</a></li>
</ul>
</div>
When the Angular application runs you will see this page with links to the newly added routing.
Route Information Example
To pass data or information between components, we can put it all within the route. For example, a first component sends an ID or object to a second component via route. There are a few ways to send information to another component. First, use URL query parameters. Open and edit src/app/bathroom/bathroom.component.ts then replace all typescript codes with this.
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-bathroom',
templateUrl: './bathroom.component.html',
styleUrls: ['./bathroom.component.css']
})
export class BathroomComponent implements OnInit {
constructor(private router: Router) { }
ngOnInit(): void {
}
gotoBedroom(message: String) {
this.router.navigate(['/bedroom'], { queryParams: { message: message } });
}
}
Next, open and edit src/app/bathroom/bathroom.component.html then replace all HTML tags with this.
<h1>bathroom works!</h1>
<h3>
<button (click)="gotoBedroom('cleaner teeth')">Go to Bedroom</button>
</h3>
So, the second component will receive this information from the first component using the queryParams method to get the message value. Second, add object params programmatically from the typescript. Open and edit src/app/bedroom/bedroom.component.ts then replace all Typescript tags with this.
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
@Component({
selector: 'app-bedroom',
templateUrl: './bedroom.component.html',
styleUrls: ['./bedroom.component.css']
})
export class BedroomComponent implements OnInit {
message: String = '';
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
this.route.queryParams.subscribe(params => {
this.message = params['message'] || '';
});
}
}
Next, open and edit src/app/bedroom/bedroom.component.html then replace all HTML tags with this.
<h1>bedroom works!</h1>
<h3>
Good, Now I have {{ message }}
</h3>
The second way, directly adds parameters to the router navigation. In the src/app/bathroom/bathroom.component.ts replace the gotoBedroom method with this.
gotoBedroom(message: String) {
this.router.navigate(['/bedroom', { message: message }]);
}
In the src/app/bedroom/bedroom.component.ts, replace the ngOnInit method with this.
ngOnInit(): void {
this.message = this.route.snapshot.paramMap.get('message') || '';
}
The third way is, to register the parameter to the app-routing.modules.ts. Just replace the routes constant in the src/app/app-routing.modules.ts.
const routes: Routes = [
{ path: 'bedroom/:message', component: BedroomComponent },
{ path: 'bathroom', component: BathroomComponent },
];
In the src/app/bathroom/bathroom.component.html, change the button to use routerLink.
<h1>bathroom works!</h1>
<h3>
<button [routerLink]="['/bedroom', 'cleaner teeth']">Go to Bedroom</button>
</h3>
In the src/app/bedroom/bedroom.component.ts, replace the ngOnInit method with this.
ngOnInit(): void {
this.message = this.route.snapshot.paramMap.get('message') || '';
}
Those ways will make a difference in the URL.
http://localhost:4200/bedroom?message=cleaner%20teeth
http://localhost:4200/bedroom;message=cleaner%20teeth
http://localhost:4200/bedroom/cleaner%20teeth
Wildcard Routes Example
In the basic Angular Routing, you just can navigate to the routing that defines in the app-routing.module.ts and URL query parameters. Unfortunately, when you point to a different URL other than that, the view will be redirected to the root URL. If you want to handle invalid URL navigation errors, you can redirect the entire undefined router by the wildcard route that defines with two asterisks "**".
Next, open and edit again src/app/app-routing.module.ts then add this wildcard route below other routes. So, it will look like this.
const routes: Routes = [
{ path: 'bedroom', component: BedroomComponent },
{ path: 'bathroom', component: BathroomComponent },
{ path: '', redirectTo: '/', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
That wildcard route required a PageNotFoundComponent. For that, generate a new component by this command.
ng g component PageNotFound
Import that component in `src/app/app-routing.module.ts` file.
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
Make a little modification to the `src/app/page-not-found/page-not-found.component.html` file by these lines of HTML tags.
<h1>Oops!</h1>
<h2>404 Not Found</h2>
<p>Sorry, an error has occured, Requested page not found!</p>
<h3>
<a routerLink="">Take Me Home </a>
</h3>
Now, when you point to the URL http://localhost:4200/kitchen, you will see this view with a button that takes you to the home view.
Nesting Routes Example
Nesting routes mean the other component that has other <router-outlet> as a parent component. The child of this component loads inside the parent component <router-outlet>. Create the new components for this example.
ng g component livingroom
ng g component sofa
ng g component desk
Next, open and edit src/app/livingroom/livingroom.component.html then replace all HTML tags with this.
<h2>Living Room</h2>
<nav>
<ul>
<li><a routerLink="sofa">Sofa</a></li>
<li><a routerLink="desk">Desk</a></li>
</ul>
</nav>
<router-outlet></router-outlet>
Next, open and edit src/app/app-routing.module.ts then add the nested routes to the routes constant.
const routes: Routes = [
// { path: 'bedroom/:message', component: BedroomComponent },
{ path: 'bedroom', component: BedroomComponent },
{ path: 'bathroom', component: BathroomComponent },
{ path: '', redirectTo: '/', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent },
{
path: 'livingroom',
component: LivingroomComponent, // this is the component with the <router-outlet> in the template
children: [
{
path: 'sofa', // child route path
component: SofaComponent, // child route component that the router renders
},
{
path: 'desk',
component: DeskComponent, // another child route component that the router renders
},
],
},
];
Don't forget to import those components.
import { LivingroomComponent } from './livingroom/livingroom.component';
import { SofaComponent } from './sofa/sofa.component';
import { DeskComponent } from './desk/desk.component';
Next, open and edit src/app/app.component.html then add this link to the new component.
<div class="content" role="main">
<ul>
<li><a routerLink="/bedroom" routerLinkActive="active">Bedroom Component</a></li>
<li><a routerLink="/bathroom" routerLinkActive="active">Bathroom Component</a></li>
<li><a routerLink="/livingroom" routerLinkActive="active">Livingroom Component</a></li>
</ul>
</div>
Custom Route Animation Example
By default, the navigation in the Angular application does not have an animated transition. For that, we will try to make a custom route or navigation transition. We still use existing components, just adding a custom route animation transition. Open and edit src/app/app.module.ts then add this import of BrowserAnimationModule.
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
Add to @NgModule imports after BrowserModule.
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule
],
Next, open and edit src/app/app-routing.ts then modify the route variable to add animation as a data field.
const routes: Routes = [
{ path: 'bedroom', component: BedroomComponent, data: { animation: 'bedroom' } },
{ path: 'bathroom', component: BathroomComponent, data: { animation: 'bathroom' } },
...
];
Next, create the src/app/app.animation.ts file to configure the animation style then fill that file with these Typescript codes.
import {
trigger, animateChild, group,
transition, animate, style, query
} from '@angular/animations';
// Routable animations
export const slideInAnimation =
trigger('routeAnimation', [
transition('articles <=> article', [
style({ position: 'relative' }),
query(':enter, :leave', [
style({
position: 'absolute',
top: 0,
left: 0,
width: '100%'
})
]),
query(':enter', [
style({ left: '-100%'})
]),
query(':leave', animateChild()),
group([
query(':leave', [
animate('300ms ease-out', style({ left: '100%'}))
]),
query(':enter', [
animate('300ms ease-out', style({ left: '0%'}))
])
]),
query(':enter', animateChild()),
])
]);
Add that animation configuration to src/app/app.component.ts by importing it first along with the RouterOutlet module.
import { slideInAnimation } from './app.animation'
import { RouterOutlet } from '@angular/router';
Add that animation to the @Component object.
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
animations: [ slideInAnimation ]
})
Add a function to enable an animation on the routable animation views.
getAnimationData(outlet: RouterOutlet) {
return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
}
Next, add route animation to the div that wrapped <router-outlet> in src/app/app.component.html.
<div [@routeAnimation]="getAnimationData(routerOutlet)">
<router-outlet #routerOutlet="outlet"></router-outlet>
</div>
Now, you will see the animated transition when going to Article Details from articles and vice versa.
That it's, the basic Angular Routing & Navigation. For more deeps about Angular Routing, we will write another example about it later. For this example, you can get the full source code on GitHub.
If you don’t want to waste your time design your own front-end or your budget to spend by hiring a web designer then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.
That just the basic. If you need more deep learning about Angular and Typescript, you can take the following cheap course:
- Angular
- Entretien: Expert Angular (dition 2023)
- Ultimate Guide to Angular Material
- Angular Router In Depth (Angular 15)
- Angular + TypeScript from Basic to Advanced + Live Project
- Mastering TypeScript - 2023 Edition
Thanks!