Many modern Javascript based front-end application create Single Page Application(SPA) which loads everything once on the browser after that user can navigate between pages/ views very quickly without loading any HTML or JS content except data.
What is Routing?
In Angular we have components, each component can have a different task, for example in Human Resource Management Application there can be a Profile, Attendance, Leaves views. Routing enables a user to visit these pages or components with each one having a specified URL path.
These URL’s or RouterLinks can be accessed by a user through hyperlinks in HTML templates, javascript’s navigate methods or by simply pasting in browser’s address bar.
Setup Routing in Angular Application
When we create a new app using Ng CLI by running this command
$ ng new MyAngularApp
it asks "Would you like to add Angular routing?" so we can add routing by pressing y, but here we will create it without routing and check which of the steps we need to follow for adding routing to an Angular project.
Let's follow steps which CLI would do if we answer above Question with y
The Router Module
First, to keep routing stuff separated from other files, CLI creates a new Routing file under app folder src/app/app-routing.module.ts with the following content
//app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
'@angular/router' implements Router service in Angular application, enables navigation from one view to the next by using RouterModule class.
Here @NgModule decorator imports & exports RouterModule. The forRoot() method available in RouterModule class takes in routes const of type Routes which will have paths defined which will have an array of Routing paths which we will discuss further.
By adding RouterModule in exports array, components declared in AppModule will get access to router directives like RouterLink and RouterOutlet.
Add Navigation Url(s)
Let's take an example of a Human Resource Management System (HRMS) Application, which can have the following main components:
DashboardComponent: Home page component to show brief information.
ProfileComponent: To check profile details.
AttendanceComponent: User can check daily attendance.
LeavesComponent: Apply leaves or check leave balance.
So, here we want DashboardComponent open by default after the user opens the application.
In that case, we will define the following path in the routes array:
{path: '', redirectTo: 'dashboard', pathMatch: 'full'}
By adding above route we defined a configuration that if path equals '' then redirectTo parameter will check for 'dashboard' path then navigate to it.
So that following must be available for redirectTo to navigate.
{ path: 'dashboard', component: DashboardComponent}
The path parameter takes the string value of URL which will be visible in the browser address bar when a user navigates.
The PathMatch Property
The pathMatch property is required with redirect route which we specified above to tell the router how to match a URL with value in the path property of route.
It can take 'full' means to match the URL fully. We can also set it to 'prefix' means it will match the beginning of the path. The 'prefix' is the default type.
Complete routes with all URL path will look like this:
//app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { ProfileComponent } from './profile/profile.component';
import { AttendanceComponent } from './attendance/attendance.component';
import { LeavesComponent } from './leaves/leaves.component';
const routes: Routes = [
{path: '', redirectTo: 'dashboard', pathMatch: 'full'},
{ path: 'dashboard', component: DashboardComponent},
{ path: 'profile', component: ProfileComponent},
{ path: 'attendance', component: AttendanceComponent},
{ path: 'leaves', component: LeavesComponent},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Other routes above will have path and component parameters to specify the component to load on navigation.
Handle Page Not Found
If we type http://localhost:4300/dashboardxyz instead of http://localhost:4300/dashboard in browser dashboard, the application will throw some console errors due to a mismatch in paths added under routes
Error: Cannot match any routes. URL Segment: 'dashboardxyz'
To handle this we can add the following path in the routes array
{ path: '**', component: PageNotFoundComponent }
The path with '**' is a wildcard. The route service will select this if the URL does not match any the provided paths. This can handle 404 type errors.
The Router Outlet Directive
Next, we have Router Outlet directive which is added to the component template where we want to show the component content.
In the app.component.html file add the following directive:
<router-outlet></router-outlet>
Add Navigation Links in Application
For navigation in the application, we can use routerLink directive.
There is also another useful directive routerLinkActive, which adds a specified class when that path is opened/ active.
In the app.component.html file add HTML link using the routerLink and routerLinkActive directive as shown below:
<ul>
<li>
<a [routerLink]="'/'" routerLinkActive="active"> Dashboard </a>
</li>
<li>
<a [routerLink]="'/profile'" routerLinkActive="active"> My Profile </a>
</li>
<li>
<a [routerLink]="'/attendance'" routerLinkActive="active"> My Attendance </a>
</li>
<li>
<a [routerLink]="'/leaves'" routerLinkActive="active"> My leaves </a>
</li>
</ul>
<router-outlet></router-outlet>
Now if you run your project $ ng serve --open you will see an error
Can't bind to 'routerLink' since it isn't a known property of 'a'.
Application is not aware of any Routing until we add AppRoutingModule in imports array in the app.module.ts file:
//app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard/dashboard.component'; import { ProfileComponent } from './profile/profile.component'; import { AttendanceComponent } from './attendance/attendance.component'; import { LeavesComponent } from './leaves/leaves.component'; @NgModule({ declarations: [ AppComponent, DashboardComponent, ProfileComponent, AttendanceComponent, LeavesComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Conclusion: So here we discussed the basic yet important concept of Routing and how we can integrate it into an Angular project using RouterModule.
In coming articles, we will discuss more concepts related to routing so stay tuned!