Telerik blogs
AngularT2 Dark_1200x303

Learn how to use the Angular Router to add routes and links that render the content we want when we navigate to the routes.

Angular is a framework that lets us create interactive web frontends for users. It lets us write single-page frontend apps that can let us show different things according to the URL we go to.

It does this by providing a routing library that lets us map URLs to components. Then when we go to a URL, we see the component that we want to render.

In this article, we will look at how to use the Angular Router to add routes and links that render the content we want when we navigate to the routes.

Angular Router

Angular apps are mostly single-page apps, but we want to render multiple pages. Therefore, we need client-side routing in our app.

Angular comes with its own client-side routing library to let us render the component we want according to the URL we are going to. We can add links that have the route URLs as the destination so that when we click on the link, we will see the content we expect.

To use it, first we have to import the AppRouting module that we will create that includes the routing code.

We write:

app.module.ts

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";

import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { FooComponent } from "./foo/foo.component";
import { BarComponent } from "./bar/bar.component";

@NgModule({
  declarations: [AppComponent, FooComponent, BarComponent],
  imports: [BrowserModule, AppRoutingModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

to import the AppRoutingModule component so that we can use routing in AppModule.

We also add FooComponent and BarComponent to register the two components in AppModule so they can be rendered.

Then we run:

ng g component Foo

and

ng g component Bar

to create the Foo and Bar components which will be our route components.

Next, we map URLs to the route components we just created in app-routing.module.ts by writing:

app-routing.module.ts

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { BarComponent } from "./bar/bar.component";
import { FooComponent } from "./foo/foo.component";

const routes: Routes = [
  { path: "foo", component: FooComponent },
  { path: "bar", component: BarComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

The path property is the URL path relative to the base URL. And the component property is set to the component that will be rendered when we go to the URL.

We add RouterModule.forRoot(routes) to the imports array to register the routes.

And we add RouterModule to the exports array so we can import RouterModule along with AppRoutingModule so that Angular will use the routes on this module when we import it in another module.

We can also add redirects easily with Angular’s router. For instance, we update app-routing.module.ts to the following:

app-routing.module.ts

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { BarComponent } from "./bar/bar.component";
import { FooComponent } from "./foo/foo.component";
import { PageNotFoundComponent } from "./page-not-found/page-not-found.component";

const routes: Routes = [
  { path: "foo", component: FooComponent },
  { path: "bar", component: BarComponent },
  { path: "", redirectTo: "/foo", pathMatch: "full" },
  { path: "**", component: PageNotFoundComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

We added { path: "", redirectTo: "/foo", pathMatch: "full" }, to redirect / to /foo. The pathMatch property is set to 'full' so that the full path has to match before the redirect takes place.

Also, we added { path: "**", component: PageNotFoundComponent } to add a wildcard route that is rendered when no routes on the list above it are matched.

Therefore, the PageNotFoundComponent’s contents is rendered when we navigate to any URL other than /foo, /bar, or /.

Also, we can set the title for each route easily. All we have to do is add the title property to the route objects.

For instance, we replace with we have in app-routing.module.ts with:

app-routing.module.ts

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { BarComponent } from "./bar/bar.component";
import { FooComponent } from "./foo/foo.component";
import { PageNotFoundComponent } from "./page-not-found/page-not-found.component";

const routes: Routes = [
  { path: "foo", title: "Foo", component: FooComponent },
  { path: "bar", title: "Bar", component: BarComponent },
  { path: "", redirectTo: "/foo", pathMatch: "full" },
  { path: "**", component: PageNotFoundComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

We just set the title property to the value we want and they will be displayed as the title of each route in the browser.

To make the title dynamic, we create a class that extends the TitleStrategy class.

For instance, we replace with we have in app-routing.module.ts with:

app-routing.module.ts

import { Injectable, NgModule } from "@angular/core";
import { Title } from "@angular/platform-browser";
import {
  Routes,
  RouterModule,
  TitleStrategy,
  RouterStateSnapshot,
} from "@angular/router";
import { BarComponent } from "./bar/bar.component";
import { FooComponent } from "./foo/foo.component";
import { PageNotFoundComponent } from "./page-not-found/page-not-found.component";

const routes: Routes = [
  { path: "foo", title: "Foo", component: FooComponent },
  { path: "bar", title: "Bar", component: BarComponent },
  { path: "", redirectTo: "/foo", pathMatch: "full" },
  { path: "**", component: PageNotFoundComponent },
];

@Injectable()
export class TemplatePageTitleStrategy extends TitleStrategy {
  constructor(private readonly title: Title) {
    super();
  }

  override updateTitle(routerState: RouterStateSnapshot) {
    const title = this.buildTitle(routerState);
    if (title !== undefined) {
      this.title.setTitle(`App | ${title}`);
    }
  }
}

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [{ provide: TitleStrategy, useClass: TemplatePageTitleStrategy }],
})
export class AppRoutingModule {}

to add the TemplatePageTitleStrategy class into app-routing.module.ts file. We make it injectable with the injectable decorator.

In the class, we add the updateTitle method which overrides the default title with our own text. We use buildTitle to return the title property value of the route. Then we call this.title.setTitle with the title we want, which includes the value of title that we got from buildTitle.

As a result, we see that the title is App | Foo when we go to /foo and is App | Bar when we go to /bar.

Now that we have the route components added and registered, we can add some links that let us reach the pages.

In app.component.html, we replace the existing content with:

app.component.html

<nav>
  <ul>
    <li>
      <a
        routerLink="/foo"
        routerLinkActive="active"
        ariaCurrentWhenActive="page"
        >Foo</a
      >
    </li>
    <li>
      <a
        routerLink="/bar"
        routerLinkActive="active"
        ariaCurrentWhenActive="page"
        >Bar</a
      >
    </li>
  </ul>
</nav>

<router-outlet></router-outlet>

We add two a elements that are rendered as links. We want them to render components that we registered, so we set the routerLink attribute to /foo and /bar respectively.

The router-outlet component lets us render the content for the component that we mapped the URL to. Therefore, we see the links on the top of the page with the content for the Foo and Bar routes below it depending on the URL we are on.

This will let us see the content of the Foo and Bar components respectively since we mapped /foo to the Foo component and /bar to the Bar component with:

const routes: Routes = [
  { path: "foo", component: FooComponent },
  { path: "bar", component: BarComponent },
];

routerLinkActive is set to the active class so the styles for the active class will be rendered when the link’s URL matches the URL of the page we are on.

To add some styles for the active class, we write:

app.component.css

.active {
  font-weight: bold;
}

to make the link text bold when the link’s URL matches the URL of the page we are on.

If we are on /foo, then Foo is highlighted. And if we are on /bar, then Bar is highlighted.

Conclusion

Angular lets us write single-page frontend apps that can let us show different things according to the URL we go to. It does this by providing a routing library that lets us map URLs to components.

Then when we go to a URL, we see the component that we want to render. We can use Angular Router to register routes by mapping URLs to route components.

Also, we can set up redirects and add wildcard routes that render a component with content that we want to show when nothing else on the route list matches the URLs listed.

And we can add router links easily so we can add links that render the components we want by adding a few attributes to regular HTML a elements.

The router-outlet component is used to render the route component contents.


About the Author

John Au-Yeung

John Au-Yeung is a frontend developer with 6+ years of experience. He is an avid blogger (visit his site at https://thewebdev.info/) and the author of Vue.js 3 By Example.

Related Posts

Comments

Comments are disabled in preview mode.