Navigating and Passing Data Between Pages
We’ve already seen how to set up routes to navigate to different parts of our application:
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
},
{
path: 'settings',
component: SettingsComponent,
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
This sets up routes for components that are not lazy loaded. More typically, we will do this to lazy load sections of our application that are broken up into modules:
{
path: 'home',
loadChildren: () =>
import('./home/home.component').then((m) => m.HomeModule),
},
and then our HomeModule
defines its own routes to determine which component to display:
RouterModule.forChild([
{
path: '',
component: HomeComponent,
},
]),
Whichever approach we are using, we now 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 to 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
:
<p>I am the home page</p>
<a routerLink="/settings">Go to settings</a>
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 { ChangeDetectionStrategy, Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-home',
template: `
<p>I am the home page</p>
<button (click)="handleLogin()">Login</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HomeComponent {
constructor(private router: 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 { ChangeDetectionStrategy, Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-home',
template: `
<p>I am the home page</p>
<button (click)="handleLogin()">Login</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HomeComponent {
constructor(private router: Router, private route: 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.