14

In my app Im trying to dynamically change the title in my header component depending on the page that Im on, so In my header component I want to use a

<h1>{{title}}</h1>

and I want it to change depending on the page that I am on. Now the header is fixed so it's on every page

below is an image of what im trying to change enter image description here

Basically if im on the home page I want it to say home and then if Im on an about page I want it to change to about..

Not sure how I can go about this and everything ive researched has been to change the title in the <head></head> tags

4
  • Are you talking about the tab title (<title></title>) or is this something specific to your app Commented Nov 13, 2017 at 4:53
  • In my header component I want to be able to have a <h1>{{title}}</h1> and title being the heading of the page depending on the page Im on so If im on an about page I want the h1 to be like <h1>About Page</h1> Commented Nov 13, 2017 at 5:00
  • If it is just a string in your app. All you need is to bind it to a component property Commented Nov 13, 2017 at 5:01
  • Its in the header, so I want to be able to change it dynamically because the header is constant while the page changes Commented Nov 13, 2017 at 5:03

5 Answers 5

26

You can create a service dedicated for updating the title in your header component. Simply inject the service in your header component and subscribe to a dedicated BehaviorSubject. Then you can inject this service in any component you have and use the setTitle method from that component which will update the title in the header component. Check out the following code

//headerTitle.service.ts
@Injectable()
export class headerTitleService {
  title = new BehaviorSubject('Initial Title');

  setTitle(title: string) {
    this.title.next(title);
  }
}

//header.component.ts
title = '';

constructor(private headerTitleService: HeaderTitleService) {}

ngOnInit() {
  this.headerTitleService.title.subscribe(updatedTitle => {
    this.title = updatedTitle;
  });
}

//header.component.html
<h1>{{title}}</h1>

//about.component.ts
constructor(private headerTitleService: HeaderTitleService) {}

ngOnInit() {
  this.headerTitleService.setTitle('About');
}

Working demo

Sign up to request clarification or add additional context in comments.

11 Comments

In my header component I want to be able to have a <h1>{{title}}</h1> and title being the heading of the page depending on the page Im on so If im on an about page I want the h1 to be like <h1>About Page</h1>
Igot an error Cannot find name 'BehaviorSubject'.
How do I subscribe to BehaviorSubject?
You will have to import it import {BehaviorSubject} from 'rxjs/subject/BehaviorSubject';
Works, but always throws an error: ERROR Error: "ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. - any idea how to fix this?
|
2

Use the title service in @angular/platform-browser and add router component with data property.

const appRoutes: Routes = [
  { path: 'home',component:HomeComponent , data:{title:'Home'}}

  ];

Call this function in the root component

ngOnInit() {
    this.router.events
      .filter((event) => event instanceof NavigationEnd)
      .map(() => this.activatedRoute)
      .map((route) => {
        while (route.firstChild) route = route.firstChild;
        return route;
      })
      .filter((route) => route.outlet === 'primary')
      .mergeMap((route) => route.data)
      .subscribe((event) => this.titleService.setTitle(event['title']));
  }
}

1 Comment

This changes browser title. He wants it in html.
1

use title service in browser platform to change the title dynamically. refer this link for more information

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule, Title }  from '@angular/platform-browser';

import { AppComponent } from './app.component';

@NgModule({
  imports: [
    BrowserModule
  ],
  declarations: [
    AppComponent
  ],
  providers: [
    Title
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

app.component.ts

// Import the native Angular services.
import { Component } from '@angular/core';
import { Title }     from '@angular/platform-browser';

@Component({
selector: 'app-root',
template:
  `<p>
    Select a title to set on the current HTML document:
  </p>

  <ul>
    <li><a (click)="setTitle( 'Good morning!' )">Good morning</a>.</li>
    <li><a (click)="setTitle( 'Good afternoon!' )">Good afternoon</a>.</li>
    <li><a (click)="setTitle( 'Good evening!' )">Good evening</a>.</li>
  </ul>
  `
})
export class AppComponent {
  public constructor(private titleService: Title ) { }

  public setTitle( newTitle: string) {
    this.titleService.setTitle( newTitle );
  }
}

1 Comment

so if web app or bookmarkable mobile app title will be wrong since only set on click event and not by route. route is the way to go. if click events on <a> that is a code smell
0

Based on OP's requirement, it seems OP needs to bind a string property to the page.

In your component have a property. Since its a fix string you can initialize it on each component like:

 public title:string = 'About me';

and in your HTML just:

<h1>{{title}}</h1>

Update:

Since it is to be bound to a constant header component, you will have to emit an event from each component using EventEmitter and listen to it across multiple components in your app and accordingly update the title property.

As suggested by Aamir in comments: You can have a service, wherein you can create an Observable and then update its next value in each component. The observable can then be subscribed in the header component to update the title property.

4 Comments

Do not ever use EventEmitter in angular except for use with @Output for event binding between a child and parent component. Do not subscribe to it. stackoverflow.com/a/36076701/2227788
I agree. But I think the specific case the OP is trying to achieve will need emission from various component which will be bound to @Input title in the header component
It's better to use a service and rxjs, in my opinion.
Yes. Can be a better way to do it.
0

You can achive this by subscribing to Router events as follows

private setTitleFromRouteData(routeData) {
    if (routeData && routeData['title']) {
        this.pageTitle = routeData['title'];
    } else {
        this.pageTitle = 'No title';
    }
}

private getLatestChild(route) {
    while (route.firstChild) {
        route = route.firstChild;
    }
    return route;
}

private subscribeToRouteChangeEvents() {
    // Set initial title
    const latestRoute = this.getLatestChild(this.activeRoute);
    if (latestRoute) {
        this.setTitleFromRouteData(latestRoute.data.getValue());
    }
    this.router.events.pipe(
        filter(event => event instanceof NavigationEnd),
        map(() => this.activeRoute),
        map((route) => this.getLatestChild(route)),
        filter((route) => route.outlet === 'primary'),
        mergeMap((route) => route.data),
    ).subscribe((event) => {
        this.setTitleFromRouteData(event);
    });
}

I have written a complete tutorial on this matter - https://medium.com/@CROSP/page-specific-dynamic-angular-components-using-child-routes-40f3cc47ce10

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.