DEV Community

Renuka Patil
Renuka Patil

Posted on

3. Routing and Navigation

Routing is the mechanism by which requests(as specified by a URL and HTTP method) are routed to the code that handles them.

Image description

  • Without page reload
  • The angular router is an essential element of the angular platform.
  • It allows developers to build single page applications with multiple states and views using routes and components and allows client side navigation and routing between the various components.
  • It's built and maintained by the core team behind developement and it's contained in the @angular/router package.
  • If you want to navigate to different pages in your application, but you also want the application to be a SPA(single Page Application), with no page reloading then you can use Angular Router.

Features in Angular Router:

  • The components, routes and paths
  • The router outlet
  • The route matching strategies
  • Route parameters
  • Query parameters
  • Route guards
  • Route resolvers
  • The RouterLink directive (replaces the href attribute)
  • Auxiliary routes
  • Primary and secondary router outlets

1.How to configure routes

Step 1: Create project, when asking for routing say yes.

ng new routing-demo
Enter fullscreen mode Exit fullscreen mode

Make
Image description

Make sure in package.json it is added:

Image description

Image description

How to add routing to an existing project:

ng generate module app-routing --flat --module=app
Enter fullscreen mode Exit fullscreen mode

lets add component:

ng g c home

ng g c about

ng g c contact
Enter fullscreen mode Exit fullscreen mode

Add paths in routing file:

const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },

];
Enter fullscreen mode Exit fullscreen mode

In app.component.html file:

<h1>Routing app demo</h1>

<router-outlet></router-outlet>
Enter fullscreen mode Exit fullscreen mode

<router-outlet>: It is a directive exported b RouterModule and acts as a placeholder that indicates to the router where it needs to insert the matched components.

You will see when we route to a specific path instead of we can see the components are rendering.

Image description

Lets create links In app.component.html file:

<h1>Routing app demo</h1>


<a routerLink="home">Home</a>
<a routerLink="about">About</a>
<a routerLink="contact">Contact</a>

<router-outlet></router-outlet>
Enter fullscreen mode Exit fullscreen mode

When we click on links the components will render.

Image description

Here I have clicked on home link that's why the home component rendered.


2.Page Not Found | Wildcards | pathMatch

Let's try to route which is not added in our routes:

Image description

There will be error because we haven't configure this path in our routing file.

Now, let's add path when user wanted to navigate which is not in our scope:

For that lets add one component:

ng g c page-not-found
Enter fullscreen mode Exit fullscreen mode

Let's add path for that:

const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  {path: '**', component: PageNotFoundComponent}

];
Enter fullscreen mode Exit fullscreen mode

Wildcards: path: '**' is called wildcard entry.

Image description

Let's configure path for empty path:

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  {path: '**', component: PageNotFoundComponent}

];

Enter fullscreen mode Exit fullscreen mode

If user enters nothing then that navigates to HomeComponent.

If I navigate to http://localhost:4200 it will automatically redirect to http://localhost:4200/home


3.Route parameters or Dynamic Routing

Image description

Let's create 2 components

ng g c employees-list 

ng g c employees-details

Enter fullscreen mode Exit fullscreen mode

Let's add path for employee-list in app-routing.module.ts

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: 'employee', component: EmployeesListComponent},
  {path: '**', component: PageNotFoundComponent}

];
Enter fullscreen mode Exit fullscreen mode

And will add link for the same in app.component.html

<h1>Routing app demo</h1>


<a routerLink="home">Home</a> <br>
<a routerLink="about">About</a> <br>
<a routerLink="contact">Contact</a> <br>
<a routerLink="employee">Employees</a> <br>

<router-outlet></router-outlet>
Enter fullscreen mode Exit fullscreen mode

Image description

Lets add create array of Employee in list

export class EmployeesListComponent implements OnInit {

  Employees = [
    {"id": 1 , "name": 'John'},
    {"id": 2 , "name": 'smith'},
    {"id": 3 , "name": 'kumar'},
    {"id": 4 , "name": 'ram'},
    {"id": 5 , "name": 'Ramesh'}
  ]

}

Enter fullscreen mode Exit fullscreen mode

To show list of employees on html

<h1>Employees List</h1>


<ul>
    <li (click) = "EmpClick(emp)"
     *ngFor="let emp of Employees">
        {{emp.id}} - {{emp.name}}
    </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Image description

Lets fetch with employee ID

app-routing.module.ts

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: 'employee', component: EmployeesListComponent},
  { path: 'employee/:id', component: EmployeesListComponent},
  {path: '**', component: PageNotFoundComponent}

];
Enter fullscreen mode Exit fullscreen mode

Employee-list.component.html

<h1>Employees List</h1>


<ul class="list-group">
    <li (click) = "EmpClick(emp)"
    class="list-group-item bg-dark text-white"
     *ngFor="let emp of Employees">
        {{emp.id}} - {{emp.name}}
    </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Employee-list.component.ts

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

export class EmployeesListComponent implements OnInit {

  Employees = [
    {"id": 1 , "name": 'John'},
    {"id": 2 , "name": 'smith'},
    {"id": 3 , "name": 'kumar'},
    {"id": 4 , "name": 'ram'},
    {"id": 5 , "name": 'Ramesh'}
  ]


  constructor(private router: Router) {

   }

   EmpClick(emp: any){
      this.router.navigate(['/employee', emp.id])
   }

}
Enter fullscreen mode Exit fullscreen mode

Added some bootstrap for better representation

Image description

Observe the link, when I click on 4th employee it routes to

http://localhost:4200/employee/4
Enter fullscreen mode Exit fullscreen mode

Now lets navigate user to the employee details:

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: 'employee', component: EmployeesListComponent},
  { path: 'employee/:id', component: EmployeesDetailsComponent},
  {path: '**', component: PageNotFoundComponent}

];
Enter fullscreen mode Exit fullscreen mode

Employee-details.component.ts


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

export class EmployeesDetailsComponent implements OnInit {

public EMPID: any;

  constructor(private activatedRoute: ActivatedRoute) { }

  ngOnInit(): void {
    let id = this.activatedRoute.snapshot.paramMap.get('id');
    this.EMPID = id;
  }

}

Enter fullscreen mode Exit fullscreen mode

Employee-details.component.ts

<h2>
    You have selected Employee with id {{EMPID}}
</h2>
Enter fullscreen mode Exit fullscreen mode

Now when you select any employee you will route to employee-details component.

Image description


4.Multiple route parameters

  { path: 'employee/:id/:name', component: EmployeesDetailsComponent},
Enter fullscreen mode Exit fullscreen mode

employee-list.component.ts


   EmpClick(emp: any){
      this.router.navigate(['/employee', emp.id, emp.name]);
   }
Enter fullscreen mode Exit fullscreen mode

employee-details.details.ts

export class EmployeesDetailsComponent implements OnInit {

public EMPID: any;

public EMPNAME: any;

  constructor(private activatedRoute: ActivatedRoute) { }

  ngOnInit(): void {
    let id = this.activatedRoute.snapshot.paramMap.get('id');
    this.EMPID = id;

    let name = this.activatedRoute.snapshot.paramMap.get('name');
    this.EMPNAME = name;
  }

}
Enter fullscreen mode Exit fullscreen mode

employee-details.component.html

<h2>
    You have selected Employee with id {{EMPID}}

    You have selected Employee with name {{EMPNAME}}
</h2>
Enter fullscreen mode Exit fullscreen mode

Image description


5.Absolute and Relative path

Image description

Example of Relative path:
The relative path is concatenated with current path that till now we have seen

Image description

Image description

In this example, if you see I want to go Home and then About and again home. This is the wrong path http://localhost:4200/about/home

When I am redirecting to Home when I am in About page the correct path should be http://localhost:4200/home

Let's add link of home page in the about page:

About.component.ts

<a routerLink="home">Home</a> <br>
Enter fullscreen mode Exit fullscreen mode

Image description

And When I click on Home link, observe we redirect to page not found

Image description

To resolve this we will use Absolute path.
we will just add / before home link:

About.component.ts

<a routerLink="home">Home</a> <br>
Enter fullscreen mode Exit fullscreen mode

Now it will successfully redirect from About to home link:

Image description

For one step back you can also do this:

About.component.ts

<a routerLink="../">Home</a> <br>
Enter fullscreen mode Exit fullscreen mode

6.paramMap observable

Let's add previous and next button on employee-details.component.ts

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

export class EmployeesDetailsComponent implements OnInit {

public EMPID: any;


  constructor(private activatedRoute: ActivatedRoute, private route: Router) { }

  ngOnInit(): void {
    let id = this.activatedRoute.snapshot.paramMap.get('id');
    this.EMPID = id;

  }


  previous(){
    let previousId= parseInt(this.EMPID) - 1;
    this.route.navigate(['/employee', previousId]);
  }
  next(){
    let nextId = parseInt(this.EMPID) + 1;
    this.route.navigate(['/employee', nextId]);

  }

}
Enter fullscreen mode Exit fullscreen mode

employee-details.component.html

<h2>
    You have selected Employee with id {{EMPID}}
</h2>


<button (click) = "previous()">Previous</button>
&nbsp;
<button (click) = "next()">Next</button>
Enter fullscreen mode Exit fullscreen mode

employee-list.component.ts

   EmpClick(emp: any){
      this.router.navigate(['/employee', emp.id]);
   }
Enter fullscreen mode Exit fullscreen mode

Image description

If you observe here our view is not updated when I click on next button, this is the drawback of snapshot approach.

We will see how we can resolve this with help of paramMap observable

  • *ParamMap * is the method of ActivatedRoute and it will return an
  • observable and it will give data only if we subscribe to it
  • The argument in the subscribe method is an arrow function.
  • The observable provides the parameter which we strongly typed to paramMap.
  • paramMap is coming from Router package.

employee-details.component.ts

  ngOnInit(): void {
    // let id = this.activatedRoute.snapshot.paramMap.get('id');
    // this.EMPID = id;

    this.activatedRoute.paramMap.subscribe((params: ParamMap) => {
      let id = params.get('id');
      this.EMPID = id;
    });

  }
Enter fullscreen mode Exit fullscreen mode

Observe here what id is in params is displayed on the view:

Image description


7.Optional Route Parameters

In Angular, route parameters allow you to pass values to a route, which can then be used by the associated component to display or process specific data. While some parameters are mandatory, others can be optional, providing flexibility in designing dynamic and user-friendly routes.

This guide explains optional route parameters, how to define them, and how to use them in Angular applications.


What Are Optional Route Parameters?

Optional route parameters are parameters that are not required to navigate to a route. If omitted, the route still works without error, making it possible to build more versatile URLs.

For example:

  • URL with parameter: /profile/123
  • URL without parameter: /profile

Both can point to the same component, but with different behavior based on whether the parameter is present.


Defining Optional Route Parameters

In Angular, optional parameters are typically defined using the query parameters or a route path configuration.

1. Using Query Parameters

Query parameters are the most common way to handle optional parameters.

Route Configuration

Define a route without hardcoding the parameter in the path:

const routes: Routes = [
  { path: 'profile', component: ProfileComponent }
];
Enter fullscreen mode Exit fullscreen mode

Navigating with Query Parameters

You can pass query parameters programmatically:

this.router.navigate(['/profile'], { queryParams: { id: 123 } });
Enter fullscreen mode Exit fullscreen mode

Accessing Query Parameters in a Component

Use the ActivatedRoute service to retrieve query parameters:

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

@Component({
  selector: 'app-profile',
  template: `<p>User ID: {{ userId }}</p>`
})
export class ProfileComponent implements OnInit {
  userId: string | null = null;

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    this.route.queryParams.subscribe(params => {
      this.userId = params['id'] || 'No ID provided';
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Using Optional Parameters in Path

You can include optional parameters in the route path using parameterized segments.

Route Configuration

Define a route with optional parameters using a wildcard approach:

const routes: Routes = [
  { path: 'profile/:id', component: ProfileComponent },
  { path: 'profile', component: ProfileComponent }
];
Enter fullscreen mode Exit fullscreen mode

Here, the id parameter is optional because the route is defined both with and without the parameter.

Navigating with Optional Parameters

Use navigate or direct links:

// With parameter
this.router.navigate(['/profile', 123]);

// Without parameter
this.router.navigate(['/profile']);
Enter fullscreen mode Exit fullscreen mode

Accessing Parameters in a Component

Use ActivatedRoute to access parameters:

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

@Component({
  selector: 'app-profile',
  template: `<p>User ID: {{ userId }}</p>`
})
export class ProfileComponent implements OnInit {
  userId: string | null = null;

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    this.route.params.subscribe(params => {
      this.userId = params['id'] || 'No ID provided';
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Combining Query Parameters and Optional Path Parameters

You can use both query parameters and optional path parameters in the same route for maximum flexibility:

const routes: Routes = [
  { path: 'profile/:id', component: ProfileComponent }
];
Enter fullscreen mode Exit fullscreen mode

Navigate with:

this.router.navigate(['/profile', 123], { queryParams: { name: 'John' } });
Enter fullscreen mode Exit fullscreen mode

Access in the component:

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

  this.route.queryParams.subscribe(params => {
    this.userName = params['name'];
  });
}
Enter fullscreen mode Exit fullscreen mode

Best Practices

  1. Use Query Parameters for Truly Optional Data

    • Ideal for filters, sorts, and non-mandatory identifiers.
  2. Provide Default Values

    • Fallback to defaults when optional parameters are not provided.
  3. Avoid Overuse of Parameters

    • Too many optional parameters can complicate route management.
  4. Document Your Routes

    • Clearly indicate which parameters are optional to avoid confusion.

Conclusion

Optional route parameters offer flexibility in designing Angular routes, enabling more dynamic navigation experiences. By using query parameters or optional path parameters, you can tailor the behavior of your application to meet diverse user needs. Mastering these techniques is essential for building scalable and user-friendly Angular applications.


8.Child Routes or Nested Routes

Product is Parent and T-shirts and Trousers components are child:

Image description

Lets create 3 component:

ng g c products
ng g c tshirts
ng g c trousers
Enter fullscreen mode Exit fullscreen mode

In app-routing.module.ts

 { path: 'products', component: ProductsComponent },
Enter fullscreen mode Exit fullscreen mode

In app.component.html

<a routerLink="products">Products</a> <br>
Enter fullscreen mode Exit fullscreen mode

Image description

Now, let's configure the child components:

In app-routing.module.ts

{
    path: 'products',
    component: ProductsComponent,
    children: [
      {path: 'tshirts', component: TshirtsComponent},
      {path: 'trousers', component: TrousersComponent}
    ]
  },
Enter fullscreen mode Exit fullscreen mode

product.somponent.html

<h2>All products are here...</h2>

<a routerLink="tshirts">T-Shirts</a> &nbsp;
<a routerLink="trousers">Trousers</a>

<router-outlet></router-outlet>
Enter fullscreen mode Exit fullscreen mode

Image description


9.Adding All The Routes Inside Bootstrap Navbar

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Navbar</a>

    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
          <a class="nav-link" routerLink="home">Home </a>
        </li>

        <li class="nav-item">
          <a class="nav-link" routerLink="products" >Products</a>
        </li>

        <li class="nav-item">
          <a class="nav-link" routerLink="about" >About</a>
        </li>

        <li class="nav-item">
            <a class="nav-link" routerLink="contact" >Contact</a>
          </li>

          <li class="nav-item">
            <a class="nav-link" routerLink="employee" >Employee</a>
          </li>


      </ul>

    </div>
  </nav>


<h1>Routing app demo</h1>


<router-outlet></router-outlet>


Enter fullscreen mode Exit fullscreen mode

Image description


10.Auxiliary Routes OR Named Routes & Multiple Router Outlets

  • Angular supports the concept of auxiliary routes, which allow you to set up and navigate multiple independent routes in a single app.
  • Auxiliary routes allow the user to access or toggle portions of the page, such as a side-bar or dialog, using the URL.
  • Each component has one primary route and zero or more auxiliary outlets.
  • Auxiliary outlets must have unique name within a component.
  • To define the auxiliary route we must first add a named router outlet where contents for the auxiliary route are to be rendered.

Image description

let's create 2 components:

ng g c courses
ng g c courses-details
Enter fullscreen mode Exit fullscreen mode

app-souting.module.ts

 { path: 'courses', component: CoursesComponent },
  {
    path: 'coursedetails',
    outlet: 'course_details',
    component: CoursesDetailsComponent
  },
Enter fullscreen mode Exit fullscreen mode

app.component.html

          <li class="nav-item">
            <a class="nav-link" routerLink="courses" >Courses</a>
          </li>

          <li class="nav-item">
            <a class="nav-link" [routerLink]="[{outlet: {course_details: ['coursedetails'] }}]" >Courses Details</a>
          </li>



<router-outlet></router-outlet>

<router-outlet name="course_details"></router-outlet>

Enter fullscreen mode Exit fullscreen mode

Output:

Image description


You can see these blogs to cover all angular concepts:

Beginner's Roadmap: Your Guide to Starting with Angular

  1. Core Angular Concepts
  2. Services and Dependency Injection
  3. Routing and Navigation
  4. Forms in Angular
  5. RxJS and Observables
  6. State Management
  7. Performance Optimization

HAPPY CODING!

Top comments (1)

Collapse
 
jangelodev profile image
João Angelo

Hi Renuka Patil,
Very nice and helpful !
Thanks for sharing.