Angular Routing - Part 2

Angular Routing - Part 2

Passing Parameters to Routes

We can incorporate parameters into our routes by utilizing dynamic segments in the paths, as demonstrated below.

//anything mentioned after colon ':' is interpreted as id
{ path: 'orders/:id', component: OrdersComponent },
{ path: 'orders/:id/:orderedBy', component: OrdersComponent }

Fetching Route Parameters

We can retrieve the parameters passed above by using the currently loaded route and injecting ActivatedRoute. The currently loaded route is a JavaScript object containing metadata about the route.

public order: { id: number; orderedBy: string };
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
    this.order = {
      id: this.route.snapshot.params['id'],
      orderedBy: this.route.snapshot.params['orderedBy'],
    };
  }

Fetching Route Parameters Reactively

In the code provided above, fetching parameters using a snapshot is effective when routing between different components. However, it does not work if we have previously visited the component.

The snapshot data is suitable for initial use, but to respond effectively to subsequent changes, we must utilize the params property of the route.

Params are observable that allow you to work with asynchronous tasks by subscribing to potential future events. This enables you to execute specific code when these events occur, without having to wait for them at the time.

this.route.params.subscribe((params: Params) => {
      //this code is executed when there is any change in the params
      this.user = {
        id: params['id'],
        name: params['orderedBy'],
      };
});

Note: Use params.subscribe only when reloading an already loaded component; otherwise, utilize the snapshot for other scenarios.

Passing Query Parameters and Fragments

Query parameters are used to transmit additional information to a route. Angular provides methods for navigation with query parameters, allowing you to customize the routeing behaviour or convey data for filtering, sorting, or various other purposes.

Fragment identifiers, also known as hash fragments, enable navigation to specific sections within a page. Angular supports navigation using fragment identifiers through the fragment option.

There are two methods for passing query parameters and fragments.

  • Using the routerLink directive and the queryParams property.
1. <a [routerLink]="['/orders', order.id , 'edit']"
   [queryParams]="{ allowEdit: '1' }"
   fragment="loading"
   href="#"
   class="list-group-item"
   *ngFor="let order of orders">{{ server.name }}
   </a>
  • Using navigate()
import { Router } from '@angular/router';

constructor(private router: Router) {}

// Navigating with query parameters
this.router.navigate(['/orders'], { queryParams: { id: 1, orderedBy: 'Sankarshan' } });

// Updating query parameters while staying on the same route
const queryParams: NavigationExtras = {
  queryParams: { id: 2, orderedBy: 'Sankarshan' },
  queryParamsHandling: 'merge' // Merge with existing query parameters
};
this.router.navigate([], queryParams);

// Navigating with a fragment identifier
this.router.navigate(['/orders'], { fragment: 'details' });

Retrieving Query Parameters

To access the query parameters in the target component, utilize the ActivatedRoute service. This service grants access to the current route's information, encompassing query parameters.

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

constructor(private route: ActivatedRoute) {}

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

  this.route.fragment.subscribe(params => {
    const fragment= params['fragment'];
  });
}

Nested Routes

Take a look at the application's below-described routes;

const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'users', component: UsersComponent },
  { path: 'users/:id/:name', component: UserComponent },
  { path: 'orders', component: OrdersComponent },
  { path: 'orders/:id', component: OrderComponent },
  { path: 'orders/:id/edit', component: EditOrderComponent },
];

You can see that it has duplicate routes for the Users and Orders components. In this scenario, we can nest them by adding child routes.

const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'users',
    component: UsersComponent,
    children: [{ path: ':id/:name', component: UserComponent }],
  },
  {
    path: 'orders',
    component: OrdersComponent,
    children: [
      { path: ':id', component: OrderComponent },
      { path: ':id/edit', component: EditOrderComponent },
    ],
  },
];

The OrdersComponent is the parent, while OrderComponent and EditOrderComponent are the children.

Note -There will be an issue If we are trying to load both the parent and child components into the router outlet in the appComponent which is reserved for all top-level routes and will load the parent component.

To load the child components, the child routes of OrdersComponent need a separate route outlet because they can't override the OrdersComponent. Instead, they should be loaded and nested into the OrdersComponent.

Handling Unknown Routes

You can define a wildcard route or a fallback route that will be matched if no other routes are discovered to handle unknown routes. When the requested route does not match any defined routes, you may use this to manage and display a particular component or carry out custom activities.

Note: Always define the wildcard route at the end after defining all the other valid routes.

const routes: Routes = [
  // Other routes...
  { path: '**', component: NotFoundComponent }
];

Did you find this article valuable?

Support Sankarshan Ramesh by becoming a sponsor. Any amount is appreciated!