Navigating and Passing Data Between Pages
We’ve already seen how to set up routes to navigate to different parts of our application:
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: 'home',
loadComponent: () =>
import('./home/home.component').then((m) => m.HomeComponent),
},
{
path: 'settings',
loadComponent: () =>
import('./settings/settings.component').then((m) => m.SettingsComponent),
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
];
We also know how to activate different components in the application using the URL, e.g:
http://localhost:4200/home
or
http://localhost:4200/settings
But, we don’t typically navigate by typing addresses into the URL bar. In this lesson, we are going to look at a few more routing and navigation concerns, specifically:
- How to navigate between various routes
- How to pass data between pages
Let’s start with some basic navigation.
Basic Navigation
As I just mentioned, we don’t want our users to have to manually change the URL. We want them to be able to click buttons, or swipe, or just be automatically navigated to where they need to go.
We can do this primarily in two ways:
- If we want the user to just click on something and then navigate to some page we can use
routerLink
in the template - If we need to navigate programatically, then we can use
router.navigate()
in the class
Let’s take a closer look at both. First, routerLink
:
import { Component } from '@angular/core';
import { RouterLink, RouterModule } from '@angular/router';
@Component({
selector: 'app-home',
template: `
<p>I am the home component</p>
<a routerLink="/settings">Go to settings</a>
`,
imports: [RouterLink],
})
export class HomeComponent {}
NOTE: In order to use routerLink
you must add either RouterLink
or
RouterModule
to the imports
array. The RouterLink
import will import
just the functionality for routerLink
whereas RouterModule
will import all
functionality related to the router (e.g. it will make <router-outlet>
available as well). If you are really looking to optimise bundle sizes, you
might prefer to only import the specific things you are using.
If we use a /
at the beginning of our route it will look up the route from the
root of the application. If we use ./
then it will look up the route relative
to the currently active route. If we did this instead:
<p>I am the home page</p>
<a routerLink="./settings">Go to settings</a>
It would actually try to find the route home/settings
which does not exist.
However, if do have child routes within individual modules the relative path can
make navigating easier.
Now let’s see how to navigate programatically. Let’s say that instead of
navigating directly to some page, we want to first perform some action. Maybe we
want to perform an authentication and then if it succeeds we want to redirect
the user to another page. In that case, we can inject the Router
and navigate
using that:
import { Component, inject } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
@Component({
selector: 'app-home',
template: `
<p>I am the home page</p>
<button (click)="handleLogin()">Login</button>
`,
})
export class HomeComponent {
private router = inject(Router);
handleLogin() {
// Do the login and then:
this.router.navigate(['settings']);
}
}
Like with our previous example, we can also use a relative route if we want.
To do that, we can supply NavigationExtras
to the navigate
command:
import { Component, inject } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-home',
template: `
<p>I am the home page</p>
<button (click)="handleLogin()">Login</button>
`,
})
export class HomeComponent {
private router = inject(Router);
private route = inject(ActivatedRoute);
handleLogin() {
// Do the login and then:
this.router.navigate(['settings'], { relativeTo: this.route });
}
}
Notice that we have also injected ActivatedRoute
to get information about the
current route. Again home/settings
does not exist so this will fail.
Using Route Params
Sometimes we don’t want to just navigate to a route, we also want to pass it some information. One way we can do this is with route parameters. The basic idea is reasonably simple. When defining the route, we use this special syntax with a colon:
{
path: 'movie/:id',
loadComponent: () =>
import('./movie/movie.component').then((m) => m.MovieComponent),
},
Now we can activate this route like this:
<a routerLink="/movie/2">Dune</a>
Then, on our Movie
page, we will be able to access that value. We will discuss
exactly how in the next section.
Usually, we will be passing in some dynamic id
or other value to a route
rather than just a static value like above. If you want, you can just drop this
in using standard interpolation: