Routing in Angular 9

Reading Time: 7 minutes

Angular is a fully-featured framework that helps in creating single-page applications(SPA). In the SPA the whole page is not reloaded every time, only the view is changed. So when the application is loaded for the first time, all the pages from the server will be not be rendered. It’s the only index.html that loads when the application is loaded. The basic aim of this blog is to help you understand the concept of routing in Angular i.e. how Angular is able to work as a SPA with the help of its own Router.
Prerequisites: Basic understanding of Angular (components, directives, architecture, etc)

Basic concepts of Routing

Angular ships with its own router which allows the user to change the URL in the URL bar. But it still uses one page to display several Components. Angular exchange major parts or all the parts of that page, so that to the user, it really looks like a new page was loaded. But behind the scenes, it is still Javascript changing a lot of parts in the DOM. Basically, Angular tricks the user to believe that multiple pages are being reloaded, which is not true of course.
Let’s take a closer look.

Angular Router is a powerful tool built and maintained by the Angular core team. It can be imported from the @angular/router package in the following way:

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

This import must be made in the file in which you want to set up your routes or to say, configure the routes (typically app.module.ts in basic applications). It provides a complete routing library which gives us access to multiple router outlets, different path matching strategies, and much more. Let’s discuss routing paths and router outlets in detail.

Configuring Routing Paths

To configure the routing paths, we must declare an array that will contain JavaScript objects having routing paths. Along with this, the corresponding component must be provided which will be loaded when that path is visited in the URL. This array must be of type “Routes” which is available to us since we imported the routes package from @angular/router.

The path we enter is the string that will be attached at the end of our domain. For example, if our domain is “localhost:4200”, then the URL will look like “localhost:4200/pathValue”. The component we enter must be a Component created by Angular or a user-defined Component. For example, if we want to load a CartComponent when a specific path is visited in the URL, we simply give the value of Component as CardComponent with the relevant path.

Enough talking, let’s see some code below which will help you understand better:

const appRoutes: Routes = [
   { path:  '', component:  HomeComponent},
   { path:  'users', component:  UsersComponent},
   { path:  'emails', component:  EmailListComponent},
];

Understanding the above code

In the above code, the first JavaScript object has an empty path, which indicates that nothing will be entered after the domain in the URL. At that time we are loading HomeComponent. Feel free to load any component of your choice on any path of your choice. The next two paths work similarly, if ‘users’ is present after our domain then it will load UsersComponent. The URL will look like this if you are working on a local machine: localhost:4200/users. Make sure you don’t add a slash “/” by yourself in configuring the routes, it is automatically managed by the Angular.

Are we ready to go ?

Even if we have configured the routes and imported the required package, these routes will not work. Confused? Well, the reason is pretty simple. How would Angular know that it needs to use the constant we created (appRoutes in this case)? We could have created multiple constants here and Angular would not know which one to pick. To solve that and make our routes work, we must add this configured constant in our imports array inside @ngModule. To add our constant, we will be using RouterModule which will be available to us if we import it from @angular/router.

So, our import will look like this now:

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

And, the imports array inside @ngModule will contain this code which will eventually register our appRoutes constant as Angular Router Configuration.

imports: [
RouterModule.forRoot(appRoutes)
]

appRoutes constant will be received here as an argument by forRoot and with that, our routes are now registered in our Angular app on this RouterModule which gives us the routing functionality, and now Angular knows our routes.

The missing piece is someplace to render the currently selected component. If we visit /users, Angular knows we want to load the users component but how does it know where we want to display it? We have not told Angular that yet. So, let’s discuss how to display the content when using Routes in Angular.

Router Outlet

Now we don’t add the components by using their selectors but we add a special directive shipping with Angular, the “router-outlet”. We just need to place this directive wherever we want Angular to display the component corresponding to our currently selected route.

<router-outlet></router-outlet>

With this all set up, we can rebuild our application and change the URL. You will notice that now our Components change as we change the path in our URL. This is happening without reloading our page. Awesome!

But, what if the user enters a path, whose route has not been set up? For that, we have wildcard routing. It is super easy to set up and it tells Angular which component to load it the URL doesn’t match any of our configured paths. Below is the code to set up this wildcard route. Make sure to add this at the end of the routes array as they follow a top-down approach. So if we add this anywhere in between or at the top, the routes below that will simply stop working!

{ path: '**', component: PageNotFoundComponent }

Until now, we have been changing the URLs manually, which is not the usual case in most of the websites. Usually, a user clicks somewhere to go to a specific section or location of a website. So, is there a way that we can change the URL with a click on a button or something and still maintain the concept of Single Page Application? The answer is, yes we can!
We will require something known as “routerLink“. Let’s discuss it now.

routerLink Directive

Angular provides the routerLink directive to create navigation links. This directive takes the path to which the URL will be changed. Hence, there is no need to give the full URL, we only need to provide the path which will be attached at the end of our domain. The reason behind this is that we are providing the relative path and not the absolute one. So for example, you want a button on your HomePage which will take you to the UsersComponent, you can simply use the following code on your HomePage.

<button routerLink="/users">All Users</button>

With that, our setup is complete. You can see that clicking on this button will take you to the UsersComponent. As an exercise, add a button on UsersComponent to take you back on the HomePage or some other component. Feel free to add more buttons in various places of the application to test your Routing.

Although, we have covered absolute basic concepts of routing but there is much more left, and hence, let’s see how we can pass some data along with routing, or to say, let’s move on to routing with parameters.

Routing With Parameters

We need to do routing with parameters in several cases, the most common of them all is to display details of a selected item in the list. For example, to display the details of the selected product from the given product list, a product ID must be passed as a parameter to the route.

In this case, the route parameters are declared in the following manner:

const appRoutes: Routes = [
  { path: 'product-list', component: ProductList },
  { path: 'product-details/:id', component: ProductDetails }
];

The “:id” in the above code is the parameter we are passing to the route. For example if we want to open the details of the 3rd product in the list, the URL will look something like this:

localhost:4200/product-details/3

Now once we have set up the routes, we must learn how to link them with our code. For this, we only have to make a minor change in the way we use routerLink directive. Now along with the component, the route parameter is mentioned in the following manner:

<a *ngFor="let product of products"
  [routerLink]="['/product-details', product.id]">
  {{ product.name }}
</a>

With this, the URL can be visited directly by clicking on the list item. But we should be able to read this URL on the product description page. For this, we need something called ActivatedRoute that will give us the params observable which we can subscribe to read the values from the URL.

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

export class ProductDetailsPage implements OnInit {
  id: number;
  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.route.params.subscribe(params => {
       this.id = +params['id'];
  }
}

The last thing we are going to learn in this blog is about child routes.

Child Routes

The child routes are used to perform routing inside already active routes. For example, when we visit the product details page, we may want to see several kinds of details like overview, technical specs, reviews, etc. Routes within the product details route are created to serve this purpose. The URL for such routes will look like this:

localhost:4200/product-details/3/reviews

The code for child routes is written in the following manner:

const routes: Routes = [
  { path: 'product-list', component: ProductList },
  { path: 'product-details/:id', component: ProductDetails,
    children: [
      { path: 'overview', component: Overview },
      { path: 'reviews', component: Review }
    ]
  }
];

However, to display child routes, we just have to use our learning from previous sections. We only need to place the <router-outlet></router-outlet> in the ProductDetails page (or the page for which you have created the child routes) of our application.

Conclusion

This was just a basic overview of how routing works in Angular. Although, it was too much to grasp still there is way more deep learning in Routing and its applications. We learned almost all the basics however, there is some advanced stuff like routing guards. I will be writing blogs on it too.
Stay connected!

For more information on Routing in Angular, visit: https://angular.io/tutorial/toh-pt5

Leave a Reply