60

我正在尝试从路由器更改页面标题,可以这样做吗?

import {RouteConfig} from 'angular2/router';
@RouteConfig([
  {path: '/home', component: HomeCmp, name: 'HomeCmp' }
])
class MyApp {}
4

14 回答 14

60

Title@EricMartinez 指出的服务有一个setTitle()方法 - 这就是设置标题所需的全部内容。

就在路由更改时自动执行此操作而言,到目前为止Router,除了订阅和调用setTitle()您的回调之外,没有内置的方法可以执行此操作:

import {RouteConfig} from 'angular2/router';
import {Title} from 'angular2/platform/browser';

@RouteConfig([
  {path: '/home', component: HomeCmp, name: 'HomeCmp' }
])
class MyApp {
    constructor(router:Router, title:Title) {
       router.events.subscribe((event)=>{ //fires on every URL change
          title.setTitle(getTitleFor(router.url));
       });
    }
 }

也就是说,我强调到目前为止,因为路由器仍在大力开发中,我希望(或至少希望)我们能够RouteConfig在最终版本中做到这一点。

编辑:

随着 Angular 2 (2.0.0) 的发布,一些事情发生了变化:

于 2016-01-05T05:31:17.327 回答
16

这是我的方法,效果很好,特别是对于嵌套路由:

在路线更改后,我使用递归辅助方法来获取最深的可用标题:

@Component({
  selector: 'app',
  template: `
    <h1>{{title | async}}</h1>
    <router-outlet></router-outlet>
  `
})
export class AppComponent {
  constructor(private router: Router) {
    this.title = this.router.events
      .filter((event) => event instanceof NavigationEnd)
      .map(() => this.getDeepestTitle(this.router.routerState.snapshot.root));
  }

  title: Observable<string>;

  private getDeepestTitle(routeSnapshot: ActivatedRouteSnapshot) {
    var title = routeSnapshot.data ? routeSnapshot.data['title'] : '';
    if (routeSnapshot.firstChild) {
      title = this.getDeepestTitle(routeSnapshot.firstChild) || title;
    }
    return title;
  }
}

这是假设您在路由的 data 属性中分配了页面标题,如下所示:

{
  path: 'example',
  component: ExampleComponent,
  data: {
    title: 'Some Page'
  }
}
于 2016-11-07T14:59:03.487 回答
13

对于 Angular 4+:

如果您想使用路由自定义数据为每个路由路径定义页面标题,以下方法将适用于嵌套路由和角度版本 4+:

您可以在路由定义中传递页面标题:

  {path: 'home', component: DashboardComponent, data: {title: 'Home Pag'}},
  {path: 'about', component: AboutUsComponent, data: {title: 'About Us Page'}},
  {path: 'contact', component: ContactUsComponent, data: {title: 'Contact Us Pag'}},

现在,在您的上层组件(即AppComponent)中最重要的是,您可以全局捕获每次路由更改的路由自定义数据并更新页面标题:

    import {Title} from "@angular/platform-browser";
    import { filter, map } from 'rxjs/operators';
    export class AppComponent implements OnInit {

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

  ngOnInit() {
    this.router
   .events.pipe(
   filter(event => event instanceof NavigationEnd),
   map(() => {
     let child = this.activatedRoute.firstChild;
     while (child) {
       if (child.firstChild) {
         child = child.firstChild;
       } else if (child.snapshot.data && child.snapshot.data['title']) {
         return child.snapshot.data['title'];
       } else {
         return null;
       }
     }
     return null;
   })).subscribe( (title: any) => {
      this.titleService.setTitle(title);
  });
}

上面的代码针对 Angular 版本 4+ 进行了测试。

于 2017-10-11T21:42:26.137 回答
11

这样做真的很容易,您可以按照以下步骤查看直接效果:

我们在 bootstrap 中提供 Title 服务:

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 { }

然后在你想要的组件中导入这个服务:

import { Component } from '@angular/core';
import { Title }     from '@angular/platform-browser';

@Component({
selector: 'my-app',
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 );
  }
}

现在单击这些链接以查看标题更改。

你也可以使用 ng2-meta 来改变页面标题和描述,你可以参考这个链接:

https://github.com/vinaygopinath/ng2-meta

于 2017-01-31T06:53:36.603 回答
5

Angular 2 提供了标题服务,请参阅 Shailesh 的答案只是该代码的副本。

我我们的 app.module.ts

import { BrowserModule, Title } from '@angular/platform-browser';
........
providers: [..., Title],
bootstrap: [AppComponent]

现在转到我们的 app.component.ts

import { Title }     from '@angular/platform-browser';
......
export class AppComponent {

    public constructor(private titleService: Title ) { }

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

将标题标签放在您的组件 html 上,它将为您读取和设置。

如果您想知道如何动态设置它和更多​​详细信息,请参阅这篇文章

于 2017-04-14T01:28:07.403 回答
3
import {Title} from "@angular/platform-browser"; 
@Component({
  selector: 'app',
  templateUrl: './app.component.html',
  providers : [Title]
})

export class AppComponent implements {
   constructor( private title: Title) { 
     this.title.setTitle('page title changed');
   }
}
于 2017-01-31T07:32:32.347 回答
3

这就是我的选择:

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

ngOnInit() {
    this.router.events.subscribe(event => {
        if (event instanceof NavigationEnd) {
            this.title.setTitle(this.recursivelyGenerateTitle(this.router.routerState.snapshot.root).join(' - '));
        }
    });
}

recursivelyGenerateTitle(snapshot: ActivatedRouteSnapshot) {
    var titleParts = <string[]>[];
    if (snapshot) {
        if (snapshot.firstChild) {
            titleParts = titleParts.concat(this.recursivelyGenerateTitle(snapshot.firstChild));
        }

        if (snapshot.data['title']) {
            titleParts.push(snapshot.data['title']);
        }
    }

    return titleParts;
}
于 2017-03-02T22:19:42.880 回答
3

Angular 6+ 我已经使用 new Pipe() 修改了旧代码并且它工作正常。

import { Title } from '@angular/platform-browser';
import { filter, map, mergeMap } from 'rxjs/operators';

...

constructor(
    private router: Router,
    public activatedRoute: ActivatedRoute,
    public titleService: Title,
  ) {
    this.setTitle();
  }

……

setTitle() {
  this.router.events.pipe(
    filter((event) => event instanceof NavigationEnd),
    map(() => this.activatedRoute),
    map((route: any) => {
      while (route.firstChild) route = route.firstChild;
      return route;
    }),
    filter((route) => route.outlet === 'primary'),
    mergeMap((route: any) => route.data)).subscribe((event) => {
      this.titleService.setTitle(event['title']);
      console.log('Page Title', event['title']);
    })
  }
于 2018-06-04T09:34:31.157 回答
2

这是在导航页面/视图时更改页面标题的最简单方法(从 Angular @2.3.1 开始测试)。只需将以下解决方案应用于您拥有的所有视图,您应该一切顺利:

关于我们页面/视图中的示例代码:

import {Title} from "@angular/platform-browser";

export class AboutUsComponent implements OnInit {

  constructor(private _titleService: Title) {
  }

  ngOnInit() {
    //Set page Title when this view is initialized
    this._titleService.setTitle('About Us');
  }

}

联系我们页面/视图中的示例代码:

import {Title} from "@angular/platform-browser";

export class ContactusComponent implements OnInit {

  constructor(private _titleService: Title) {
  }

  ngOnInit() {
    //Set page Title
    this._titleService.setTitle('Contact Us');
  }

}
于 2017-05-08T07:07:47.167 回答
2

在下面的示例中:

-我们将数据对象:{title:'NAME'}添加到任何路由对象。

-我们为上传时间设置了一个基本名称(“CTM”)(点击F5进行刷新时..)<title>CTM</title>:。

-我们添加了“TitleService”类。

- 我们通过从 app.component.ts 过滤它们来处理 Routher 事件。

索引.html:

<!DOCTYPE html>
<html>
  <head>
    <base href="/">
    <title>CTM</title>
  </head>

...

app.module.ts:

import { NgModule, enableProdMode } from '@angular/core';
import { BrowserModule  } from '@angular/platform-browser';
import { TitleService }   from './shared/title.service';
...


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

enableProdMode();

标题.service.ts:

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


@Injectable()
export class TitleService extends Title {

    constructor() {
        super();
    }


    private recursivelyGenerateTitle(snapshot: ActivatedRouteSnapshot) {
        var titleParts = <string[]>[];
        if (snapshot) {
            if (snapshot.firstChild) {
                titleParts = this.recursivelyGenerateTitle(snapshot.firstChild);
            }

            if (snapshot.data['title']) {
                titleParts.push(snapshot.data['title']);
            }
        }

        return titleParts;
    }

    public CTMGenerateTitle(snapshot: ActivatedRouteSnapshot) {
        this.setTitle("CTM | " + this.recursivelyGenerateTitle(snapshot).join(' - '));
    }

}

应用程序路由.module.ts:

import { Injectable } from '@angular/core';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { MainComponent } from './components/main.component';

import { Router, CanActivate } from '@angular/router';
import { AuthGuard }          from './shared/auth/auth-guard.service';
import { AuthService }    from './shared/auth/auth.service';


export const routes: Routes = [
  { path: 'dashboard', component: MainComponent, canActivate: [AuthGuard], data: { title: 'Main' } },
];

@NgModule({
    imports: [
        RouterModule.forRoot(routes, { useHash: true })  // .../#/crisis-center/
    ],
    exports: [RouterModule],
    providers: [
..
    ]
})

export class AppRoutingModule { }

export const componentsOfAppRoutingModule = [MainComponent];

app.component.ts:

import { Component } from '@angular/core';
import { Router, NavigationEnd, ActivatedRouteSnapshot } from '@angular/router';
import { TitleService } from './shared/title.service';

@Component({
  selector: 'ctm-app',
  template: `
    <!--<a [routerLink]="['/dashboard']">Dashboard</a>
    <a [routerLink]="['/login']">Login</a>
    <a [routerLink]="['/']">Rooting</a>-->
    <router-outlet></router-outlet>
    `
})
export class AppComponent {

    constructor(private router: Router, private titleService: TitleService) {

        this.router.events.filter((event) => event instanceof NavigationEnd).subscribe((event) => {
            console.log("AppComponent.constructor: Setting HTML document's Title");
            this.titleService.CTMGenerateTitle(this.router.routerState.snapshot.root);
        });

    }


}
于 2017-06-12T09:58:13.340 回答
2

在 Angular 6 和 6+ 中使用 Pipe 和 map 方法而不是使用过滤器可以正常工作

Step1:路由设置

{path: 'dashboard', component: DashboardComponent, data: {title: 'My Dashboard'}},
{path: 'aboutUs', component: AboutUsComponent, data: {title: 'About Us'}},
{path: 'contactUs', component: ContactUsComponent, data: {title: 'Contact Us Page'}},

step2:在你的 app.module.ts 导入模块

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

然后在提供者中添加提供者:[title]

第 3 步 在您的主要组件导入中

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

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

    }

ngOnInit() {

    this.router.events.pipe(map(() => {
        let child = this.activatedRoute.firstChild;
        while (child) {
            if (child.firstChild) {
                child = child.firstChild;
            } else if (child.snapshot.data && child.snapshot.data['title']) {
                return child.snapshot.data['title'];
            } else {
                return null;
            }
        }
        return null;
    })).subscribe(title => {
        this.titleService.setTitle(title);
    });

}
于 2019-01-04T05:33:43.543 回答
0

角度 6+

如果路由配置如下:-

Routes = [
     {  path: 'dashboard',
       component: DashboardComponent,
       data: {title: 'Dashboard'}
   }]

**然后可以在组件构造函数中设置标题如下:- **

 constructor( private _titleService: Title, public activatedRoute: ActivatedRoute) {
    activatedRoute.data.pipe(map(data => data.title)).subscribe(x => this._titleService.setTitle(x));
   }
于 2018-06-25T11:30:09.097 回答
0

我还可以推荐我刚刚发布的@ngx-meta/core插件插件,以防您正在寻找一种动态设置页面标题和元标记的方法。

于 2016-11-11T08:48:25.123 回答
0

设置标题的简单通用方法:

import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';

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

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

  ngOnInit() {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        const { title } = this.activatedRoute.firstChild.snapshot.data;
        this.titleService.setTitle(title);
      }
    });
  }

}

需要title在每条路线上设置的位置,例如:

{ path: '', component: WelcomeComponent, data: {title: 'Welcome to my app'} }
于 2020-03-01T17:27:23.420 回答