Skip to content

Instantly share code, notes, and snippets.

@abarrak
Forked from pniel-cohen/app.module.ts
Last active September 22, 2020 14:21
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save abarrak/448af33925e46257fefe0faf27f62e76 to your computer and use it in GitHub Desktop.
Save abarrak/448af33925e46257fefe0faf27f62e76 to your computer and use it in GitHub Desktop.
Dynamically set page title based on active route in Angular 6+ .. (Corrected & Simplified Version)
import { Component, OnInit } from '@angular/core';
import { TitleService } from './shared/title/title.service';
@Component({
selector: 'ny-app',
templateUrl: './app.component.html',
styles: [],
})
export class AppComponent implements OnInit {
constructor(private titleService: TitleService) { }
ngOnInit() {
this.titleService.boot();
}
}
import ...
@NgModule({
...
providers: [ TitleService ],
})
export class AppModule { }
const routes: Routes = [{
path: '',
component: HomeComponent,
data: {title: "My Home Page"},
}, {
path: 'detail/:id',
component: DetailComponent,
}];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ExampleRoutingModule { }
import { Injectable } from '@angular/core';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { filter, map, switchMap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class TitleService {
default_title = 'My App'
constructor(
private router: Router,
private activeRoute: ActivatedRoute,
private title: Title
) { }
boot() {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => this.activeRoute),
map(route => route.firstChild),
switchMap(route => route.data),
map((data) => {
return data && data.title ? `${data.title} • ${this.default_title}` : this.default_title;
})
).subscribe((current_title) => this.title.setTitle(current_title));
}
}
@wojciech-marciniak
Copy link

Well done in an elegant way. Thought about handling ActivatedRoute params as well? I mean - mapping them to subtitles.
Your solution is also useful while used with Gtag to avoid a single boring "Angular App" page title in Analytics.

@tiboprea
Copy link

tiboprea commented Apr 25, 2020

Thanks for sharing this. I've tweaked your solution in order to make it work with lazy loaded modules.

import { Injectable } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { filter, map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class TitleService {
  defaultTitle = 'RemoveBounce.com'

  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
    private title: Title,
  ) {
  }

  boot() {
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
        map(() => {
          let child = this.activatedRoute.firstChild;
          while (child.firstChild) {
            child = child.firstChild;
          }
          if (child.snapshot.data['title']) {
            return child.snapshot.data['title'];
          }
          return this.defaultTitle;
        }),
    ).subscribe((currentTitle) => this.title.setTitle(currentTitle));
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment