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'
}
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'
}
}
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';
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';
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';
In our app constructor, pass in the following:
constructor(
private activatedRoute: ActivatedRoute,
private title: Title,
private router: Router
)
Now let’s create a function called setPageTitle.
setPageTitle(): void {
}
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';
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));
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)
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;
}
})
The setPageTitle function is complete. All that’s left to do is call it when the app component is initialized.
ngOnInit(): void {
this.setPageTitle();
}
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));
}
Visit our website at https://nightwolf.dev and follow us on Facebook and Twitter!
Top comments (3)
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
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.
cool, thank you