Angular 6 - Unable to retrieve static data

穿精又带淫゛_ 提交于 2019-12-10 19:58:17

问题


Problem: static data defined at route is never retrieved with subscription to data object at ActivatedRoute. Everything else seems to work fine, the data object is not null, but I can't get data from it. When I try to debug the data from the data object it outputs "undefined", when I try to bind it to UI nothing shows up, but when I look at ActivatedRoute messages in Chrome it has the data. After many tries I'm pretty sure my syntax should work based on many examples, so has something changed in Angular 6 perhaps, or something wrong with Angular?

Route code:

    const appRoutes: Routes = [
  {
    path: "article",
    redirectTo: "/article/partners",
    pathMatch: "full"
  },
  { 
    path: "article",
    children: [
      {
        path: "bawo",
        component: BawoArticleComponent,
        data: { title: 'BaWo' }
      },
      {
        path: "goldenhands",
        component: GoldenHandsArticleComponent,
        data: { title: 'Golden Hands' }
      },
      {
        path: "investors",
        component: InvestorsArticleComponent,
        data: { title: 'Investors' }
      },
      {
        path: "partners",
        component: PartnersArticleComponent,
        data: { title: 'Partners' }
      }
    ]
  },
  {
    path: "**",
    redirectTo: "/article/partners"
  }
];

Retrieval component code (I've commented where the relevant code is):

export class ArticleSelectorComponent implements OnInit {
  arrowFader: string;

  opacity: string;

  fadeTimer: Observable<number>;

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

  ngOnInit() {
    this.router.events.subscribe((e: RouterEvent) => {
      this.fadeTimer = timer(0, 150);
      let subscription = this.fadeTimer.subscribe(currentValue => {

        let calc = currentValue & 3;

        if (calc == 0) {
          this.arrowFader = '>';
          this.opacity = '0.5';
        }
        else if (calc == 1) {
          this.arrowFader = '>>';
          this.opacity = '0.65';
        }
        else {
          this.arrowFader = '>>>';
          this.opacity = '0.8';
        }
      });

      this.fadeTimer.subscribe(currentValue => {
        if(currentValue >= 14) {
          subscription.unsubscribe();
          this.opacity = '1.0';
        }
      });
    });

// THIS DOESN'T WORK!!!!
    this.activatedRoute.data.subscribe((data: Data) => {
      console.log(data['title']);
    });
  }

// not relevant, this code is ran with parameter at html buttons
  navToArticle(num: number) {
    let navStr = '';
    switch(num){
      case 1: {
        navStr = '/article/bawo';
        break;
      }
      case 2: {
        navStr = '/article/goldenhands';
        break;
      }
      case 3: {
        navStr = '/article/partners';
        break;
      }
      case 4: {
        navStr = '/article/investors';
        break;
      }
    }

    this.router.navigateByUrl(navStr);
  }
}

HTML code for AppComponent (with component directives):

<div class="site">

    <div class="top">
        <div class="anim-in-left">
            <app-domains></app-domains>
        </div>

        <div class="anim-in-down top-title">
            <h1 class="top-title-text">{{ topTitle }}</h1>
        </div>

        <div class="anim-in-right">
            <app-presence></app-presence>
        </div>
    </div>

    <div class="anim-in-up middle">
        <app-article-selector></app-article-selector>
    </div>
</div>

回答1:


Try Below Snippet, Because if you subscribe to activatedRoute immediately it subscribes only to the router data changes where the current component is registered in router configuration and I just added NavigationEnd filter so it wont be triggered for all other events which is not needed for this requirement.

...    
ngOnInit() {
  ...
  this.title$ = this.router.events.pipe(
    filter((event) => event instanceof NavigationEnd),
    map(_ => this.activatedRoute),
    map((route) => {
      while (route.firstChild) {
        route = route.firstChild;
      }

      return route;
    }),
    mergeMap((route) => route.data),
    map((data) => data.title)
  );
  this.title$.subscribe(title => console.log(title));
  ...
}
...



回答2:


I forked the Angular example and duplicated your code (to an extent) at ->

  • https://stackblitz.com/edit/angular-pbn7dq?file=src/app/app-routing.module.ts
  • https://stackblitz.com/edit/angular-pbn7dq?file=src%2Fapp%2Fheroes%2Fheroes.component.ts
  • https://stackblitz.com/edit/angular-pbn7dq?file=src%2Fapp%2Farticle.selector.component.ts
  • https://stackblitz.com/edit/angular-pbn7dq?file=src%2Fapp%2Fhero-detail%2Fhero-detail.component.ts

The only difference I found was how the component was being activated.

  1. ArticleSelectorComponent is never part of routing lifecycle when just imported as as an object.
  2. The moment it is made part of routing lifecycle (as a routing component) it works like a charm :D

I haven't tried @abinesh-devadas response but that looks like a better solution, if you really want to obtain the data element irrespective of component lifecycle.




回答3:


Fortunately, the question has been answered already:

https://stackoverflow.com/a/46305085/1510754

https://github.com/angular/angular/issues/11812#issuecomment-248820529

Based on this here is a more complete answer:

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

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

export class AppComponent implements OnInit {

  private baseTitle = 'MySite';

  get title(): string {
    return this.titleService.getTitle();
  }

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

  ngOnInit() {
    this.router.events.subscribe(event => {
      if (event instanceof RoutesRecognized) {
        const route = event.state.root.firstChild;
        let title = this.baseTitle;
        if (route.data['title']) {
          title = route.data['title'] + ' - ' + title;
        }
        this.titleService.setTitle(title);
      }
    });
  }

}

Note: the title getter is not needed for setting the <title> as this is done with the titleService. But you can use the getter for updating a <h1> for instance.




回答4:


The code below worked fine until recently:

this.router.events
    .pipe(
        filter((event: any) => 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']);
            console.log(event);
        }

Since the upgrade to Angular 6.0 I think. No matter what I try I get undefined.



来源:https://stackoverflow.com/questions/50912789/angular-6-unable-to-retrieve-static-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!