3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 11

Navigating and Passing Data Between Pages

STANDARD

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:

STANDARD
Key

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).