DEV Community

Cover image for Page Titles in Angular - Guide πŸš€
Priya jain
Priya jain

Posted on • Originally published at priya.today

Page Titles in Angular - Guide πŸš€

Page title is a piece of text you can see on a tab in your browser next to favicon. Setting good page title enhancing the user's navigation experience and SEO.

Static Method

1. Componenet based -

  • The simplest way to set a page title in Angular is by using the Title service provided by @angular/platform-browser. This service allows you to set the document title dynamically.
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {

  constructor(private titleService: Title) { }

  ngOnInit(): void {
    this.titleService.setTitle('Home - MyApp');
  }
}
Enter fullscreen mode Exit fullscreen mode

Problem

  • Limited Scalability: Using the static approach works for small apps only.
  • Not Centralized: This method is not scalable and not centralized.
  • Maintenance Overhead: If you change the way you want to show the title, application-level changes are required.

2. Route based title

From angular version 14, we can update the page title more easily.
Angular expose us to the optional title property in the route definition.

const routes: Routes = [
  { path: 'home', component: HomeComponent, title: 'Home Page' }, // defined a title prop
];
Enter fullscreen mode Exit fullscreen mode

However, passing static strings isn’t a convenient way and we often need to create title based on some dynamic value.

Dynamic Method

For dynamic page titles, we have two options:

1. Component Level

Below Anglar 14, You can dynamically set the title within your components by using the Title service and subscribing to route data changes. This method involves writing custom logic in each component that needs a dynamic title.

Here's how you can do it:

  • Inject the Title and ActivatedRoute services:
  • Subscribe to the route data and set the title:
const routes: Routes = [
  { path: 'home', component: HomeComponent, data: {title: 'Home Page'} }, // defined a title prop
];
Enter fullscreen mode Exit fullscreen mode
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { filter, map } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  constructor(private titleService: Title, private router: Router) {}

  ngOnInit() {
    this.router.events
      .pipe(
        filter(event => event instanceof NavigationEnd),
        map(() => {
          let route: ActivatedRoute = this.router.routerState.root;
          while (route.firstChild) {
            route = route.firstChild;
          }
          return route.snapshot.data['title'];
        })
      )
      .subscribe((title: string) => {
        if (title) {
          this.titleService.setTitle(`My App - ${title}`);
        }
      });
  }
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Injecting Services: We inject the Title and Router services.
  • Subscribing to Router Events: We subscribe to the NavigationEnd event to detect when navigation has finished.
  • Retrieving Route Data: We traverse the activated route tree to get the deepest child route's data and extract the title property.
  • Setting the Title: We use the TitleService to set the document's title.

Key Points:

  • Location: This logic resides in the root component (AppComponent).
  • Routing Events: It listens to routing events (NavigationEnd) and updates the title based on the route data.
  • Title Setting: The title is set using TitleService within the component.
  • Flexibility: This approach is straightforward and easy to understand but can become cumbersome if you need to apply it across multiple components or routes.

2. Custom TitleStrategy

A more scalable approach is to use a custom TitleStrategy. This allows you to centralize and standardize how titles are set across your application. Here's how you can implement this:

Creating a Custom Title Strategy
First, create a custom TitleStrategy class:

import { Injectable } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { TitleStrategy, RouterStateSnapshot } from '@angular/router';

@Injectable({
  providedIn: 'root',
})
export class CustomTitleStrategy extends TitleStrategy {
  constructor(private titleService: Title) {
    super();
  }

  updateTitle(snapshot: RouterStateSnapshot): void {
    const title = this.buildTitle(snapshot);
    if (title !== undefined) {
      this.titleService.setTitle(`My App - ${title}`);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Configuring the Router
Next, configure the router to use this custom strategy:

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes),
     { provide: TitleStrategy, useClass: CustomTitleStrategy },
  ],
});

Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Location: The title handling logic is abstracted away from the components and encapsulated in a service (CustomTitleStrategy).
  • Routing Events: It automatically hooks into the Angular router’s lifecycle.
  • Title Setting: The title is set using TitleService within the CustomTitleStrategy.
  • Flexibility: This approach is more modular and reusable. It centralizes the title management logic, making it easier to maintain and extend. ### 3. Using Resolvers to set page titles

In this case Angular allows us to pass a resolver to dynamically create a title. Let’s create a title resolver to display product name as a title on details page:

 const productNameTitleResolver: ResolveFn<string> = (
  route: ActivatedRouteSnapshot,
): string => {
  const productId = route.paramMap.get('id');
  return productId ? inject(ProductsService).getById(productId).name : '';
};

export const ROUTES: Routes = [
  {
    path: 'products',
    component: ProductsComponent,
    title: 'Products',
    children: [
      {
        path: ':id',
        component: ProductDetailsComponent,
        title: productNameTitleResolver
      },
    ],
  },
  {
    path: 'cart',
    component: CartSummaryComponent,
    title: 'Cart Summary'
  },
];
Enter fullscreen mode Exit fullscreen mode

The title resolver can be used like any other resolver, allowing you to inject dependencies, perform some logic, or return an Observable or Promise the returns the page title string.

Conclusion

Setting page titles in Angular can greatly enhance user experience and SEO. For small applications, using the Title service in individual components might suffice. However, for larger applications, adopting a custom TitleStrategy provides a scalable and centralized solution for managing page titles.

By understanding and implementing these techniques, you can ensure that your Angular application provides a consistent and dynamic browsing experience for users while also reaping the benefits of improved search engine optimization.

Additionally, I got to learn a new pattern in design called the Strategy Pattern while working on the CustomTitleStrategy. I will write my next article on this topic.


Happy Coding πŸ™‚

Top comments (0)