mtpultz
mtpultz

Reputation: 18268

Angular 14 Access Route Config Title Property in Component

Is it possible to read the title out of the route.snapshot.data of the routeConfig in Angular 14? I can see it in the route.snapshot.data as a Symbol, but can't seem to access it:

{
  path: 'example',
  title: 'Title of Page',
  component: ExamplePage
}
this.route.snapshot.data[Symbol('RouteTitle')]) // undefined
console.log(this.route.snapshot.data) // { Symbol('RouteTitle'): 'Title of Page' }

I'm using the TitleStrategy to update the title to be:

${title} | ${companyName}`

But want to get the pre-strategy title in the component for use in the page so they match without using the Title service to getTitle and slicing the companyName off each time.

Upvotes: 2

Views: 5827

Answers (4)

Jaime
Jaime

Reputation: 498

Starting on version 14.2.0, the router expose the resolved title (#46826).

You can do this:

@Component({/* Configuration */})
export class ExamplePage implements OnInit {

  constructor(private readonly route: ActivatedRoute) { }

  ngOnInit() {
    this.activatedRoute.title.subscribe({
      next: (title) => {
        // Use Page Title
      }
    });
  }
}

Upvotes: 0

Miss Henesy
Miss Henesy

Reputation: 123

I was just experiencing this very same problem in Angular 14, made especially more complicated because I am using a "title resolver" on one of my routes, in order to create a dynamic title for each post page.

It turns out the way to retrieve the title is through "TitleStrategy", which has a method called "getResolvedTitleForRoute". (See the Angular page for TitleStrategy for more info)

Here's how I achieved it in my app.component.ts file (I am including more than you need, probably, but I find that context can be helpful :-) ):

import { Component, Inject, Renderer2, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, DOCUMENT } from '@angular/common';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, NavigationEnd, Router, RouterState, TitleStrategy } from '@angular/router';


declare const gtag: Function; // <------------Important: the declaration for gtag is required!

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'My Generic App Title';

  constructor(
    private router: Router,
    private titleStrategy: TitleStrategy,
    private renderer: Renderer2,
    @Inject(DOCUMENT) private _document: any,
    @Inject(PLATFORM_ID) private platformId: Object) {
      if (isPlatformBrowser(this.platformId)) {
        this.injectScripts();
        this.handleRouteEvents();
      }
  }

  injectScripts() {
     // Injects a Google Tag Manager script
  }

  handleRouteEvents() {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        const p_path = event.urlAfterRedirects;
        const p_location = this._document.location.href;
        const p_title = this.getTitle(this.router.routerState, this.router.routerState.root).join('-').trim();
        console.log('p_title: |', p_title, '|');
        console.log('p_path: ', p_path);
        console.log('p_location: ', p_location);
        gtag('event', 'page_view', { 
          'page_title': p_title ? p_title : p_path,
          'page_path': p_path,
          'page_location': p_location
        });
      }
    });

  }

  getTitle(state: RouterState, parent: ActivatedRoute): string[] {
    const data = [];
    
    if (parent && parent.snapshot && this.titleStrategy.getResolvedTitleForRoute(parent.snapshot)) {
      data.push(this.titleStrategy.getResolvedTitleForRoute(parent.snapshot));
    }
    if (state && parent && parent.firstChild) {
      data.push(...this.getTitle(state, parent.firstChild));
    }
    return data;
  }

Upvotes: 1

Russ
Russ

Reputation: 631

I have a case where I still need to use title.setTitle('Foo'); so that my browser tab's text shows the name of my app when a user is logging in (kind of like a default title until they go to an actual page).

As such, I'm not able to retrieve the current route's title with the above or with title.getTitle();.

For me, I had to inject Angular's Router and then do the following (Angular 14):

const routeTitle: string = this.router.config.find((route: Route): boolean => route.path.includes(url))?.title as string;

Where url comes from the url property of RouterEvent.

Upvotes: 0

Get Off My Lawn
Get Off My Lawn

Reputation: 36311

Get the title from the snapshot.routeConfig, it returns a Route that contains the snapshots title:

{
  path: 'example',
  title: 'Title of Page',
  component: ExamplePage
}
@Component({/* Configuration */})
export class ExamplePage implements OnInit {

  constructor(private readonly route: ActivatedRoute) { }

  ngOnInit() {
    console.log(this.route.snapshot.routeConfig?.title);
    // Output: Title of Page
  }
}

Upvotes: 9

Related Questions