Vraag Een gegevenseigenschap ophalen op een Angular2-route, ongeacht het niveau van route nesten met behulp van ActivatedRoute


Ik heb een aantal routes als volgt gedefinieerd:

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

Sommige routes zijn kinderen van anderen.

Ik zou graag een manier willen vinden om de titleKey eigendom op data ongeacht of de route een route op het hoogste niveau is of het kind van een ander.

Dit is wat ik heb geprobeerd:

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

Kan iemand u adviseren hoe u een woning op de route kunt ophalen? data ongeacht het nestniveau van de route?

Bewerk: Na het lezen van de official hoekige documentatie over ActivatedRoute, Ik probeerde het te gebruiken map operator op de eigenschap data van de ActivatedRoute bijvoorbeeld als volgt:

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

en toch key is altijd ongedefinieerd ...


13
2017-08-10 15:04


oorsprong


antwoorden:


Ik stuitte op een leuke tutorial met een schone oplossing: https://toddmotto.com/dynamic-page-titles-angular-2-router-events.

Hier is wat ik uiteindelijk bedacht heb met het gebruiken van de oplossing uit de bovenstaande tutorial en het gebruik van de ng2 service vertalen om het te converteren titleKeys aangegeven in mijn routegegevens in de juiste labels:

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

5
2018-02-12 23:10



We hadden hetzelfde probleem. We besloten het op een andere manier te doen. In plaats van te proberen te luisteren naar de gegevens die worden uitgezonden op de geactiveerde route, abonneren we ons op de events Waarneembaar op de router zelf:

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

Merk op dat we de waarde gebruiken in een component die op het hoogste niveau wordt gebruikt, maar de gegevens van de diepste onderliggende route nodig heeft. Je zou dit vrij eenvoudig moeten kunnen omzetten naar een dienst die gebeurtenissen uitgezonden wanneer het titleKey verandert de waarde.

Ik hoop dat dit helpt.


3
2017-11-08 21:06



Bijwerken

U kunt hieronder proberen 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 '';
    }
   }

lijkt weinig hacky maar werkt.

Oud

Je kunt hieronder proberen,

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

voeg een nieuwe service toe MessageConversationResolve.ts en voeg het op passende wijze toe aan providers.

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

Hieronder is hoekige versie die bovenstaande oplossing ondersteunt,

Angular 2 version : 2.0.0-rc.5

Angular Router version : 3.0.0-rc.1

Ik hoop dat dit helpt!!


1
2017-08-12 20:28