Website-Suche

angular - Abrufen einer Daten-Eigenschaft auf einer Angular2-Route unabhängig von der Ebene der Routenschachtelung mit ActivatedRoute


Ich habe eine Reihe von Routen wie folgt definiert:

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'}}]
    }]
  }];

Einige der Routen sind Kinder von anderen.

Ich möchte eine Möglichkeit finden, die Eigenschaft titleKey von data abzurufen, unabhängig davon, ob die Route eine oberste Route oder ein Kind einer anderen ist.

Hier ist, was ich versucht habe:

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'] ist undefined.

Kann mir bitte jemand erklären, wie man eine Eigenschaft auf der Route data abrufen kann, unabhängig von der Verschachtelungsebene der Route?

bearbeiten: Nach dem Lesen der offiziellen Angular-Dokumentation über ActivatedRoute habe ich versucht, den map-Operator auf die Daten-Eigenschaft der ActivatedRoute-Instanz wie folgt anzuwenden:

@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));
  }
}

und doch ist key immer undefiniert...

Antwort #1

Wir hatten dasselbe Problem. Wir beschlossen, es auf eine andere Weise anzugehen. Anstatt zu versuchen, auf die Datenübertragungen des ActivatedRoute zu hören, abonnieren wir das events-Observable direkt am Router:

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;
                    }
                }
            });
    }
}

Beachten Sie, dass wir den Wert in einer Komponente verwenden, die auf oberster Ebene genutzt wird, aber die Daten aus der tiefsten Kindroute benötigt. Sie sollten in der Lage sein, dies ziemlich einfach in einen Dienst umzuwandeln, der Ereignisse ausgibt, wann immer sich der titleKey ändert.

Ich hoffe, das hilft.

Antwort #2

Ich bin auf ein schönes Tutorial mit einer sauberen Lösung gestoßen: https://toddmotto.com/dynamic-page-titles-angular-2-router-events.

Hier ist, was ich schließlich unter Verwendung der Lösung aus dem obigen Tutorial und dem ng2-Übersetzungsservice entwickelt habe, um die in meinen Routendaten angegebenen titleKeys in richtige Bezeichnungen umzuwandeln:

@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));
  }
}

Verwandte Artikel