In this post we’ll see how to navigate to a route programmatically or dynamically using router.navigate()
or router.navigateByUrl()
methods in Angular.
Navigating to a route dynamically Angular example
You may have a scenario where you would like to navigate to a route based on an event like click of a button, clicking a link. Here is a simple example which uses router.navigate() method to navigate to a route on a click of a button.
Note that while navigating to a route you can use both absolute as well as relative path. In this post we'll see examples
of both.
There is a menu as shown below and you have to show the corresponding component on click of the menu option.
1. Creating routing module
We’ll create a separate routing file app-routing.module.ts with routes array to define route paths and component they map to.
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AccountsComponent } from './accounts/accounts.component';
import { AccountComponent } from './accounts/account/account.component';
import { HomeComponent } from './home.component';
import { ServiceComponent } from './service.component';
const routes: Routes = [
{path: '', component: HomeComponent},
{path: 'account', component: AccountsComponent},
{path: 'service', component: ServiceComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
2. Import the AppRoutingModule into AppModule (app.module.ts) and add it to the imports array.
import { AppRoutingModule } from './app-routing.module';
imports: [
BrowserModule,
AppRoutingModule
],
3. Adding the configured routes to the application.
Code for menu and adding link for routes is done in the app.component.html template itself for this example.
<nav class="navbar navbar-expand-md bg-dark navbar-dark">
<div class="container-fluid">
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="nav navbar-nav">
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
<a class="nav-link" routerLink="/">Home</a>
</li>
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" routerLink="/account">Accounts</a>
</li>
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" routerLink="/service">Services</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row"><p></p></div>
<div class="row">
<div class="col-md-12">
<router-outlet></router-outlet>
</div>
</div>
</div>
Creating components
Now as per our route mapping there are 3 components HomeComponent, AccountsComponent and ServiceComponent.
Home Component (home.component.ts)
From the home page you want to provide a button to take to AccountsComponent. That route navigation will be done programmatically.
import { OnInit, Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-home',
templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
userId = 'UID0023';
constructor(private router: Router) { }
ngOnInit() {
}
navigateToAccount(){
this.router.navigate(['/account']);
}
}
To use Router.navigate method first you need to inject the Router class in your component. That is done in the constructor.
In the method navigateToAccount()
, router.navigate() method is used to navigate to a route. In navigate method you pass an array of elements
that are joined together to create a path. For example router.navigate(‘account’, 1) resolves to a path /account/1.
If you want to use router.navigateByUrl() method then you can also use this.router.navigateByUrl('/account');
With router.navigateByUrl() you can pass an absolute path, for example router.navigateByUrl(‘/account/1’).
Note that in this example path passed in this.router.navigate(['/account']); is an absolute path (not relative).
home.component.html
<h4>Welcome to XYZ Bank</h4>
<p>{{ userId }} logged in.</p>
<div>
<button type="button" class="btn btn-primary" (click)="navigateToAccount()">My Accounts</button>
</div>
Account Component (account.component.ts)
import { Component } from '@angular/core';
@Component({
selector: 'app-accounts',
templateUrl: './accounts.component.html'
})
export class AccountsComponent {
accounts = ['A1001', 'A1002'];
}
accounts.component.html
<div class= "row">
<div class="col-xs-4 col-md-6">
<h2>Account Numbers</h2>
<!-- [routerLink]=""
(click)="onAccountClick(account)" -->
<div class="list-group">
<a class="list-group-item"
*ngFor="let account of accounts">
{{ account }}
</a>
</div>
</div>
</div>
Service Component (service.component.ts)
import { Component } from "@angular/core";
@Component({
selector: 'app-service',
templateUrl:'./service.component.html'
})
export class ServiceComponent{
services = [
'Deposit Money',
'Open FD',
'Mail Customer Care'
];
}
service.component.html
<h2>Services Offered</h2>
<div class="row">
<div class="col-xs-12 col-sm-6">
<div class="list-group">
<a
href="#"
class="list-group-item"
*ngFor="let service of services">
{{ service }}
</a>
</div>
</div>
</div>
Add these components in the declarations array of the AppModule before running the example.
You will have a button in the HomeComponent which navigates you to the AccountsComponent when clicked.
Dynamic route Navigation using relative path in Angular
In the previous example we used absolute path with navigate() method but you can also pass a relative path but in that case you need to specify
path is relative to which existing path.
Let’s change the previous example to have one more component AccountComponent that shows the details for the account selected in
AccountsComponent.
For that routes array will have to be changed in the following way-
const routes: Routes = [
{path: '', component: HomeComponent},
{path: 'account', component: AccountsComponent},
{path: 'account/:acctno', component: AccountComponent},
{path: 'service', component: ServiceComponent}
];
As you can see a new route definition is added- {path: 'account/:acctno', component: AccountComponent}, here :acctno is a placeholder
that matches any account number so URL like account/A001 or account/A002 both will match this route.
Accounts component is also changed-
import { Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-accounts',
templateUrl: './accounts.component.html'
})
export class AccountsComponent {
accounts = ['A1001', 'A1002'];
constructor(private router: Router, private route: ActivatedRoute) {}
onAccountClick(account: string){
this.router.navigate([account], {relativeTo:this.route});
}
}
Along with Router class now ActivatedRoute class is also injected into the component. ActivatedRoute class provides access to information
about a route associated with a component that is loaded in router outlet.
In router.navigate() method you can also pass a second argument of type navigationExtras. One of the NavigationExtras is relativeTo which
specifies a root URI to use for relative navigation.
In the example navigate method is now like this-
this.router.navigate([account], {relativeTo:this.route});
Here this.route specifies the route associated with the component, in our case it will be /account so relative path is
http://localhost:4200/account
[account] specifies the account number that is clicked which can be either A1001 or A1002. Thus the navigation route is derived as
either http://localhost:4200/account/A1001 or http://localhost:4200/account/A1002 which matches the route definition
{path: 'account/:acctno', component: AccountComponent}.
AccountComponent (account.component.ts)
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-account',
templateUrl: './account.component.html'
})
export class AccountComponent implements OnInit{
acctNo: string;
account: {accountnumber: string, type: string, balance: number};
constructor(private route: ActivatedRoute){ }
accountDetails = [
{
accountnumber: 'A1001',
type: 'Saving',
balance: 22000
},
{
accountnumber: 'A1002',
type: 'Checking',
balance: 1000
}
];
ngOnInit() {
this.acctNo = this.route.snapshot.params['acctno'];
this.account = this.accountDetails.find(e=>e.accountnumber === this.acctNo);
}
}
Here we have defined an account type- account: {accountnumber: string, type: string, balance: number};
There is also an array with values for account.
In ngOnInit() using the passed account number we find the related object in the array using the find() method.
Account number parameter is extracted from the route using the current snapshot of the route.
this.route.snapshot.params['acctno'];
account.component.html
<h2>Account Details</h2>
<div class="row">
<div class="col-xs-6">
<label>Account Number: </label> {{ account.accountnumber }}
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label>Account Type: </label> {{ account.type }}
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label>Balance: </label> {{account.balance}}
</div>
</div>
Accounts Component
Account Component