Reputation: 57
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>
Upvotes: 3
Views: 2603
Reputation: 3893
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.
Upvotes: 1
Reputation: 1186
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
.
Upvotes: 0
Reputation: 2085
I forked the Angular example and duplicated your code (to an extent) at ->
The only difference I found was how the component was being activated.
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.
Upvotes: 1
Reputation: 1547
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));
...
}
...
Upvotes: 5