DEV Community

Cover image for Dynamically Set Page Title in Angular App
nightwolfdev
nightwolfdev

Posted on • Updated on • Originally published at nightwolf.dev

Dynamically Set Page Title in Angular App

The title tag is used to display the HTML page title in the browser’s title bar. It is a required tag and important for search engine optimization. An Angular application is considered a single page application (SPA). If there’s only one page generated, how do you display different titles for each of your pages? Let’s learn how!

Angular 14 Update

As of Angular version 14, there is now a dedicated title property! You no longer need to listen to route changes and apply the title like the rest of this article explains. Just add the title property to your route!

{ 
  path: 'about',
  component: AboutComponent,
  title: 'About'
}
Enter fullscreen mode Exit fullscreen mode

Route Data

A typical Angular route will define the following:

  • path – the url of the page
  • component – the component to load when a user visits the page

There’s nothing stopping us from adding additional information to each route. For example, we could include the page title! Let’s create a property called data, which will hold any other information we want about each route. Create a property called title in the data object.

{ 
  path: 'about',
  component: AboutComponent,
  data: { 
    title: 'About'
  } 
}
Enter fullscreen mode Exit fullscreen mode

Router Events

As a user navigates around the Angular application, the router emits events. We can listen to these events, specifically the one called NavigationEnd, which is when the navigation ends, and capture the route data that holds our page title.

We need the Router to listen for navigation events, the ActivatedRoute to know what page the user is currently on, and the NavigationEnd event. Let’s import those from the router package.

import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
Enter fullscreen mode Exit fullscreen mode

We need the Title service, which provides us the ability to set the page title. You can import the Title service from the platform browser package.

import { Title } from '@angular/platform-browser';
Enter fullscreen mode Exit fullscreen mode

When we’re listening to the router events, we’ll need a couple RxJS operators to help us out. The filter operator will help us filter events related to NavigationEnd only. The map operator will allow us to return the data the way we need.

import { filter, map } from 'rxjs/operators';
Enter fullscreen mode Exit fullscreen mode

In our app constructor, pass in the following:

constructor(
  private activatedRoute: ActivatedRoute,
  private title: Title,
  private router: Router
)
Enter fullscreen mode Exit fullscreen mode

Now let’s create a function called setPageTitle.

setPageTitle(): void {

}
Enter fullscreen mode Exit fullscreen mode

Create a variable called defaultPageTitle and set it to whatever you want the title to be if the route has no title defined.

const defaultPageTitle = 'Default Page Title';
Enter fullscreen mode Exit fullscreen mode

We want to subscribe to the router events, eventually passing in the title to the setTitle function, which will set the page title.

this.router.events.pipe(

).subscribe((title: string) => this.title.setTitle(title));
Enter fullscreen mode Exit fullscreen mode

Because we’re only interested in the NavigationEnd event, we need to filter what’s coming through the pipe. Let’s add the filter operator and limit it to the instance of NavigationEnd.

filter(event => event instanceof NavigationEnd)
Enter fullscreen mode Exit fullscreen mode

Now add the map operator, which we’ll use to return the title. We need to figure out if this is a single route or if there are child routes. If there are no child routes, return the active route’s title or the default page title if the active route’s title is not defined. If a child route exists, we need to loop through all child routes until you find the last child. Then we can return the child route’s title or the default page title if the child route’s title is not defined.

map(() => {
  let child = this.activatedRoute.firstChild;

  if (!child) {
    return this.activatedRoute.snapshot.data.title || defaultPageTitle;
  }

  while (child.firstChild) {
    child = child.firstChild;
  }

  if (child.snapshot.data.title) {
    return child.snapshot.data.title;
  }
})
Enter fullscreen mode Exit fullscreen mode

The setPageTitle function is complete. All that’s left to do is call it when the app component is initialized.

ngOnInit(): void {
  this.setPageTitle();
}
Enter fullscreen mode Exit fullscreen mode

Navigate around the application and the browser should display the respective page title!

Here’s the complete code for the setPageTitle function.

private setPageTitle(): void {
  const defaultPageTitle = 'Default Page Title';

  this.router.events.pipe(
    filter(event => event instanceof NavigationEnd),
    map(() => {
      let child = this.activatedRoute.firstChild;

      if (!child) {
        return this.activatedRoute.snapshot.data.title || defaultPageTitle;
      }

      while (child.firstChild) {
        child = child.firstChild;
      }

      if (child.snapshot.data.title) {
        return child.snapshot.data.title || defaultPageTitle;
      }
    })
  ).subscribe((title: string) => this.title.setTitle(title));
}
Enter fullscreen mode Exit fullscreen mode

Visit our website at https://nightwolf.dev and follow us on Facebook and Twitter!

Top comments (3)

Collapse
 
monacodelisa profile image
Esther White • Edited

Angular 14.2.0 - I get ->
Property 'setTitle' does not exist on type 'string'.

everything is correctly imported in
app.module.ts and app.component.ts
routing is fine,
npm paskages are also updated

Collapse
 
nightwolfdev profile image
nightwolfdev

See the Angular 14 Update section at the top of the article. As of Angular 14, you can use the title property on your route to define a title. You don't need to do what the rest of the article is explaining.

Collapse
 
monacodelisa profile image
Esther White

cool, thank you