SoFunction
Updated on 2025-04-08

Angular 2 How to implement dynamic page titles using Router events and Title

Angular2 provides us with a Service called Title for modifying and obtaining page titles, but it wouldn't be too low if we can just set the title for each page in the ngOnInit method of each page, and it does not conform to the figure of Angular2 high (zhuang) and large (bi). The result we want is to be able to dynamically change the page title when the page changes, so the best solution is to use a combination of Router events and Title Service.

Title Service

Naturally, you must first introduce it when using Service, but be aware that Title Service is not in @angular/core, but in @angular/platform-browser:

import { Title } from '@angular/platform-browser';

After introduction, it is naturally necessary to inject it into the current component, which is usually done using constructor:

import { Title } from '@angular/platform-browser';
import {Component} from '@angular/core';
@Component({})
export class AppComponent {
  constructor(private titleService: Title) {
    // Use it everywhere  }
}

Obviously, Title Service should have some methods to operate page titles. Whether it is searching for documents or source code, we can easily know that there are only two methods:

  • getTitle() is used to get the title of the current page
  • setTitle(newTitle: String) is used to set the title of the current page

If you simply set the page title statically, you can use the setTitle method directly in the ngOnInit method:

// import bala...
@Component({})
export class AppComponent implements OnInit {
  constructor(private titleService: Title) {
    // Use it everywhere  }

  ngOnInit() {
    ('New Title Here');
  }
}

It is a better time to use the setTitle method to set the document title in ngOnInit. Of course, you can also use the setTitle method anywhere according to your needs.

Router and Router events

The process of using Router and using Title Service is basically the same. It is introduced first and then injected. However, it should be noted that the similarity between Router and Title Service is not located in @angular/core, but in @angular/router:

import { Title } from '@angular/platform-browser';
import {Component} from '@angular/core';
import {Router} from '@angular/router';
@Component({})
export class AppComponent {
  constructor(private titleService: Title, private router: Router) {
    // Use and roam everywhere  }
}

Router configuration

In Angular2, pages are redirected through the correspondence between URLs, Router and Component. Router regards the URL in the browser as an operation guide, and can navigate to a view generated by the client and pass parameters to the corresponding components supporting the view. So we need to define the routing table:

// import bala...
export const rootRouterConfig: Routes = [
 { path: '', redirectTo: 'home', pathMatch: 'full'},
 { path: 'home', component: HomeComponent, data: {title: 'Home-Liu'} },
 { path: 'about', component: AboutComponent, data: {title: 'About-Liu'} },
 { path: 'github', component: RepoBrowserComponent,
  children: [
   { path: '', component: RepoListComponent, data: {title: 'GitHub List'} },
   { path: ':org', component: RepoListComponent,
    children: [
     { path: '', component: RepoDetailComponent, data: {title: 'Repo'} },
     { path: ':repo', component: RepoDetailComponent, data: {title: 'RepoDetail'} }
    ]
   }]
 },
 { path: 'contact', component: ContactComponent, data: {title: 'Contact-Liu'} }
];
 

Pay attention to the correspondence between the path and the component, and in order to get the page title in the Router event, we provide data data for some pages in the routing table, and set the title attribute representing the page title in the data.

Router Event

Using the Router event, we can achieve the purpose of dynamically changing the page title, but the placement is very important. We choose to use subscribe to the Router event in the ngOnInit method of AppComponent. Because AppComponent is the root component, we can subscribe to all Router events:

ngOnInit() {
 
  .subscribe((event) => {
   (event);  // Including NavigationStart, RoutesRecognized, NavigationEnd  });
}

Of course we are interested in the NavigationEnd event here:

import {ActivatedRoute} from '@angular/router';
// import bala...

// other codes

ngOnInit() {
 
  .subscribe((event) => {
   if (event instanceof NavigationEnd) {
    ('NavigationEnd:', event);
   }
  });
}

Of course, there is nothing wrong with using this method of judgment and filtering, but it is not elegant enough in the current front-end world. We should use filter in RxJS to achieve our goal:

import 'rxjs/add/operator/filter';
// import bala...

// other codes

ngOnInit() {
 
 .filter(event => event instanceof NavigationEnd) // Filter the original Observable: .subscribe((event) => {
  ('NavigationEnd:', event);
 });
}

Of course, if we want to dynamically change the title of a certain page, we need to obtain the routing information corresponding to the currently displayed page, which can be obtained through ActivatedRoute. Its usage method is similar to Title Service and Router. I won't go into details:

import { Title } from '@angular/platform-browser';
import {Component, OnInit} from '@angular/core';
import {Router, NavigationEnd, ActivatedRoute} from '@angular/router';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
@Component({})
export class AppComponent implements OnInit {
 constructor(private titleService: Title, private router: Router, private activatedRoute: ActivatedRoute) {
  // Use and roam everywhere }

 ngOnInit() {
  
  .filter(event => event instanceof NavigationEnd)
  .map(() => ) // Process the Observable after filter processing again  .subscribe((event) => {
   ('NavigationEnd:', event);
  });
 }
}

Note that we used RxJS againmapTo achieve our goals more gracefully.

It seems that we have finished a lot of things, but it is not enough. We have not processed subroutines, that is, the children attribute in our routing configuration above, so we also need to traverse the routing table to obtain the corresponding routing information for each page:

ngOnInit() {
 
 .filter(event => event instanceof NavigationEnd)
 .map(() => )
 .map((route) => {
  while() {
   route = ;
  }
  return route;
 })
 .subscribe((event) => {
  ('NavigationEnd:', event);
 });
}

Finally, we need to get the data information we pass in for each route in the routing table, and then use Title Service to set the page title:

ngOnInit() {
 
  .filter(event => event instanceof NavigationEnd)
  .map(() => )
  .map(route => {
   while () route = ;
   return route;
  })
  .mergeMap(route => )
  .subscribe((event) => (event['title']));
}

Below is the final code, or you can also check it on GitHubComplete code

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';

@Component({...})
export class AppComponent implements OnInit {
 constructor(
  private router: Router,
  private activatedRoute: ActivatedRoute,
  private titleService: Title
 ) {}
 ngOnInit() {
  
   .filter(event => event instanceof NavigationEnd)
   .map(() => )
   .map(route => {
    while () route = ;
    return route;
   })
   .filter(route =>  === 'primary')
   .mergeMap(route => )
   .subscribe((event) => (event['title']));
 }
}

Reference Documents

Angular2 routing guidance

Angualr2 ActivatedRoute Documentation

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.