Angular 14 brought forward a new service provided in root: TitleStrategy, which basically does what we did before in SEO in Angular: Static page titles using route data. Now we can set the title as a direct property of the route. So let's dig in and see how we can create our service spin off.
Updating SEO service
If we do absolutely nothing except set the title
attribute in any of our routes like this:
// example route
const routes: Routes = [
{
path: 'details',
component: ContentDetailsComponent,
title: 'Details'
}
];
Building and browsing to the route immediately takes over the page title. This is not what we want, we want to control it. That's when we need to create an override. First, a revisit to our SEO project in StackBlitz, then a clean up of the code that was responsible for doing something similar.
In root app.component
, we had an event subscriber that updated the title whenever a routing event occurred:
// root app.component adaptation
export class AppComponent {
constructor(
//...
) {
// this is no longer needed since the TitleStrategy service
// already catches such events
/* this.router.events
.pipe(filter((e) => e instanceof NavigationEnd))
.subscribe((event) => {
let route = this.activatedRoute.snapshot;
while (route.firstChild) {
route = route.firstChild;
}
this.seoService.setPage((<any>route.data)?.title);
});
*/
}
}
Next let's create a new service that extends
the TitleStrategy
. Looking at the source code, the buildTitle
gets the deepest route title, as expected.
// /services/title.service.ts
@Injectable({ providedIn: 'root' })
export class AppTitleStrategy extends TitleStrategy {
constructor(private seoService: SeoService) {
super();
}
// override updateTitle which is similar to catching NavigationEnd
override updateTitle(routerState: RouterStateSnapshot) {
// this retrieves the title value of the deepest child in the route
const title = this.buildTitle(routerState);
// now set the title using Title service
// but we are going to use our previously created service: SeoService
this.seoService.setPage(title);
}
}
To put it to use, we need to overwrite it in the providers array at root level, or in the root routing module to keep things organized:
// routing.module.ts
NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
// new: title strategy here
providers: [{ provide: TitleStrategy, useClass: AppTitleStrategy }],
})
export class AppRoutingModule {}
You might want to look at how we used similar Resources technique in Twisting Angular Localization
Happy coding. 🙂
Want to be updated of new articles on Sekrab Garage: Subscribe to Sekrab Parts newsletter
Top comments (0)