无论使用ActivatedRoute的路由嵌套级别如何,都在Angular2路由上检索数据属性

时间:2016-08-10 15:04:07

标签: angular typescript angular2-routing

我已经定义了许多路线如下:

export const AppRoutes: Routes = [
  {path: '', component: HomeComponent, data: {titleKey: 'homeTitle'}},
  {path: 'signup', component: SignupComponent, data: {titleKey: 'SIGNUP_FORM.TITLE'}},
  {path: 'signin', component: SigninComponent, data: {titleKey: 'SIGNIN_FORM.TITLE'}},
  {path: 'sendpasswordresetinformation', component: SendPasswordResetInformationComponent},
  {path: 'password/reset/:userAccountToken', component: PasswordResetComponent},
  {
    path: 'dashboard', component: DashboardComponent, children: [
    {path: '', component: DashboardSummaryComponent},
    {
      path: 'message', children: [
      {path: '', component: MessageSummaryComponent, data: {titleKey: 'MESSAGE_LIST.TITLE'}},
      {path: 'conversation/:otherId', component: MessageConversationComponent, data: {titleKey: 'XXX'}}]
    },
    {
      path: 'useraccount', component: UserAccountComponent, children: [
      {
        path: '',
        component: UserAccountSummaryComponent,
        data: {titleKey: 'XXX'},
        resolve: {
          userAccount: UserAccountResolve
        }
      },
      {path: 'address', component: UserAccountAddressComponent, data: {titleKey: 'ADDRESS_FORM.TITLE'}},
      {path: 'email', component: UserAccountEmailComponent, data: {titleKey: 'EMAIL_FORM.TITLE'}},
      {
        path: 'emailnotification',
        component: UserAccountEmailNotificationComponent,
        data: {titleKey: 'EMAIL_NOTIFICATION_FORM.TITLE'}
      },
      {path: 'firstname', component: UserAccountFirstNameComponent, data: {titleKey: 'FIRST_NAME_FORM.TITLE'}},
      {path: 'password', component: UserAccountPasswordComponent, data: {titleKey: 'PASSWORD_FORM.TITLE'}}]
    }]
  }];

有些路线是其他路线的孩子。

我想找到一种方法来检索titleKey上的data属性,无论该路线是顶级路线还是另一条路线的孩子。

以下是我的尝试:

export class AppComponent implements OnInit {

  constructor(private translate: TranslateService,
              private sessionService: SessionService,
              private titleService: Title,
              private activatedRoute: ActivatedRoute) {
    let userLang = 'fr';
    translate.use(userLang);
    moment.locale(userLang);
  }

  ngOnInit() {
    this.sessionService.reloadPersonalInfo();
  }

  setTitle($event) { 
    this.translate.get(this.activatedRoute.snapshot.data['titleKey'])
     .subscribe(translation=>this.titleService.setTitle(translation));
  }
}

this.activatedRoute.snapshot.data['titleKey']undefined

有人可以建议如何在路线data上检索物业,而不管路线的嵌套程度如何?

修改:在阅读官方angular documentation about ActivatedRoute后,我尝试在map实例的数据属性上使用ActivatedRoute运算符,如下所示:

@Component({
  selector: 'app',
  template: `
              <section class="container-fluid row Conteneur">
                 <appNavbar></appNavbar>
                 <section class="container">
                    <router-outlet (activate)="setTitle($event)"></router-outlet>
                 </section>
              </section>
              <section class="container-fluid">  
                <appFooter></appFooter>
              </section>
              `,
  directives: [NavbarComponent, FooterComponent, SigninComponent, HomeComponent, ROUTER_DIRECTIVES]
})
export class AppComponent implements OnInit {

  constructor(private translate: TranslateService,
              private sessionService: SessionService,
              private titleService: Title,
              private activatedRoute: ActivatedRoute) {
    let userLang = 'fr';
    translate.use(userLang);
    moment.locale(userLang);
  }

  ngOnInit() {
    this.sessionService.reloadPersonalInfo();
  }

  setTitle($event) {
    this.activatedRoute.data.map(data=>data['titleKey'])
      .do(key=>console.log(key))
      .switchMap(key=>this.translate.get(key))
      .subscribe(translation=>this.titleService.setTitle(translation));
  }
}

然而key总是未定义......

3 个答案:

答案 0 :(得分:6)

我偶然发现了一个包含干净解决方案的精彩教程:https://toddmotto.com/dynamic-page-titles-angular-2-router-events

以下是我最终使用上述教程中的解决方案并使用ng2 translate service将我的路由数据中指定的titleKeys转换为正确的标签:

@Component({
  selector: 'app',
  encapsulation: ViewEncapsulation.None,
  styleUrls: ['../styles/bootstrap.scss'],
  template: `<section class="container-fluid row Conteneur">
                 <app-navbar></app-navbar>
                 <section class="container">
                    <router-outlet></router-outlet>
                 </section>
              </section>
              <section class="container-fluid">  
                <app-footer></app-footer>
              </section>`
})
export class AppComponent implements OnInit {

  constructor(private translate: TranslateService,
              private sessionSigninService: SessionSigninService,
              private titleService: Title,
              private router: Router,
              private activatedRoute: ActivatedRoute) {
    let userLang = 'fr';
    translate.use(userLang);
    moment.locale(userLang);
  }

  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)
      .mergeMap(data => this.translate.get(data['titleKey']))
      .subscribe(translation => this.titleService.setTitle(translation));
  }
}

答案 1 :(得分:4)

我们遇到了同样的问题。我们决定以另一种方式去做。我们不是试图监听ActivatedRoute上的数据发出,而是在路由器本身上订阅events Observable:

import { Component } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";

declare var module: any;

@Component({
    moduleId: module.id,
    selector: "app-layout",
    templateUrl: "main-layout.component.html"
})
export class LayoutComponent {
    titleKey: string;

    constructor(private router: Router){}

    ngOnInit() {
        this.router.events
            .filter((event: any) => event instanceof NavigationEnd)
            .subscribe(() => {
                var root = this.router.routerState.snapshot.root;
                while (root) {
                    if (root.children && root.children.length) {
                        root = root.children[0];
                    } else if (root.data && root.data["titleKey"]) {
                        this.titleKey = root.data["titleKey"];
                        return;
                    } else {
                        return;
                    }
                }
            });
    }
}

请注意,我们正在使用顶层使用的组件中的值,但需要来自最深子路径的数据。只要titleKey更改值,您就可以非常轻松地将其转换为发出事件的服务。

希望这有帮助。

答案 2 :(得分:1)

<强>更新

您可以在AppComponent

下面尝试
   constructor(private translate: TranslateService,
          private sessionService: SessionService,
          private titleService: Title,
          private activatedRoute: ActivatedRoute) {

      this.router.events.subscribe((arg) => {
         if(arg instanceof NavigationEnd) { 
           console.log(this.getTitle(this.activatedRoute.snapshot));
         }
      });
   }

   getTitle = (snapshot) => {
     if(!!snapshot && !!snapshot.children && !!snapshot.children.length > 0){
      return this.getTitle(snapshot.children[0]);
     }
    else if(!!snapshot.data && !!snapshot.data['titleKey']){
      return snapshot.data['titleKey'];
    }
    else{
      return '';
    }
   }

似乎有点hacky但有效。

<强>旧

您可以尝试以下,

{
  path: 'conversation/:otherId', 
  component: MessageConversationComponent, 
  data: {titleKey: 'XXX'},
  // add below resolve
  resolve: {
            titleKey: MessageConversationResolve
  }      
}

添加新服务 MessageConversationResolve.ts ,并在提供商中正确添加。

import { Injectable } from '@angular/core';
import { Router, Resolve,ActivatedRouteSnapshot } from '@angular/router';
import { Observable }             from 'rxjs/Observable';

@Injectable()
export class AdminDetailResolve implements Resolve<any> {
  constructor(private router: Router,
              private titleService: Title) {}

  resolve(route: ActivatedRouteSnapshot): Observable<any> | Promise<any> | any {
    // route.data will give you the titleKey property
    // console.log(route.data);
    // you may consume titleService here to setTitle

    return route.data.titleKey;
 }
}

以下是支持上述解决方案的角度版本,

Angular 2 version : 2.0.0-rc.5

Angular Router version : 3.0.0-rc.1

希望这会有所帮助!!