How to change page title with routing in Angular application?
You have a TitleService in Angular 5. Inject it in your component's constructor, and use the setTitle()
method.
import {Title} from "@angular/platform-browser";
....
constructor(private titleService:Title) {
this.titleService.setTitle("Some title");
}
Here are the docs from Angular: https://angular.io/guide/set-document-title
Here is tested way to set page title on Angular 8 but you can use it on Angular 5 as well. Once you set this you have to just set title on route file and all will set automatically.
import { Component } from '@angular/core';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { filter, map } from "rxjs/operators";
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor (private router: Router, private activatedRoute: ActivatedRoute, private titleService: Title) {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => {
let child = this.activatedRoute.firstChild;
while (child) {
if (child.firstChild) {
child = child.firstChild;
} else if (child.snapshot.data && child.snapshot.data['title']) {
return child.snapshot.data['title'];
} else {
return null;
}
}
return null;
})
).subscribe( (data: any) => {
if (data) {
this.titleService.setTitle(data + ' - Website Name');
}
});
}
}
And on route file you can do something like this:
const routes: Routes = [
{
path: 'dashboard',
component: DefaultDashboardComponent,
data: {
title: 'Dashboard'
}
}
];
In Angular v14, there is a built-in strategy service for collecting the title from the route based on the primary router outlet, and setting the browser's page title.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AboutComponent } from './about.component';
import { HomeComponent } from './home.component';
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
title: "'My App - Home' // <-- Page title"
},
{
path: 'about',
component: AboutComponent,
title: "'My App - About Me' // <-- Page title"
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
See here
Here's a non-recursive solution that also fixes the replication of titles in case of path-less or component-less nested routes.
Make sure to add Angular's Title
service to your application: https://angular.io/guide/set-document-title.
Then in your app.component.ts
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(
private readonly router: Router,
private readonly titleService: Title
) { }
ngOnInit() {
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd)
).subscribe(() => {
this.titleService.setTitle(this.getNestedRouteTitles().join(' | '));
});
}
getNestedRouteTitles(): string[] {
let currentRoute = this.router.routerState.root.firstChild;
const titles: string[] = [];
while (currentRoute) {
if (currentRoute.snapshot.routeConfig.data?.title) {
titles.push(currentRoute.snapshot.routeConfig.data.title);
}
currentRoute = currentRoute.firstChild;
}
return titles;
}
getLastRouteTitle(): string {
let currentRoute = this.router.routerState.root.firstChild;
while (currentRoute.firstChild) {
currentRoute = currentRoute.firstChild;
}
return currentRoute.snapshot.data?.title;
}
}
Accessing the specific routeConfig.data
prevents the repetition of the inherited title
attribute.
And in main-routing.module.ts
or any of your other routing files:
const routes: Routes = [
{
path: '',
component: MainComponent,
data: { title: 'MyApplication' },
children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{
path: 'dashboard',
loadChildren: () => import('../dashboard/dashboard.module').then(m => m.DashboardModule),
data: { title: 'Dashboard' }
},
{
path: 'settings',
loadChildren: () => import('../settings/settings.module').then(m => m.SettingsModule),
data: { title: 'Settings' }
}
]
}
]
}
];