'How to get current route custom data in angular 2?
I have set up routes is like below
const appRoutes: Routes = [
{
path: 'login',
component: LoginComponent,
data: {
title: 'Login'
}
},
{
path: 'list',
component: ListingComponent,
data: {
title: 'Home Page',
module:'list'
}
},
{
path: '',
redirectTo: '/login',
pathMatch: 'full'
},
];
now when i come to '/list'
route then on 'listing.component.ts'
i have written below code
export class ListingComponent {
public constructor(private router:Router) {
//here how i can get **data** of **list** routes
}
}
Solution 1:[1]
public constructor(private route:ActivatedRoute, private router:Router) {
console.log(route.snapshot.data['title'])
}
Solution 2:[2]
For Angular 4+
If you place the following code in the parent or upper level components like AppComponent
then it won't work. It only works on child or lower level components for which you've defined the route custom data:
public constructor(private route:ActivatedRoute, private router:Router) {
console.log(route.snapshot.data['title']);
}
So, if you want to access the route custom data globally from a parent or upper level component to access the change in the route custom data then you've to listen to router events particularly RoutesRecognized
or NavigationEnd
events. I'm gonna show two procedures with AppComponent
with two events:
First Approach:
export class AppComponent implements OnInit, AfterViewInit {
constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
ngOnInit() {
this.router
.events
.filter(event => event instanceof NavigationEnd)
.map(() => {
let child = this.activatedRoute.firstChild;
while (child) {
if (child.firstChild) {
child = child.firstChild;
} else if (child.snapshot.data && child.snapshot.data['custom_data']) {
return child.snapshot.data['custom_data'];
} else {
return null;
}
}
return null;
}).subscribe( (customData: any) => {
console.log(customData);
});
}
}
Second Approach is using:
this.router.events
.filter(event => event instanceof RoutesRecognized)
.map( (event: RoutesRecognized) => {
return event.state.root.firstChild.data['custom_data'];
})
.subscribe(customData => {
console.log(customData);
});
Note: Even though last one is shorter and usually works, but, if you have nested routes then it is encouraged to use the first one.
Solution 3:[3]
After I tested various solution, the angular support group answer actually solved this problem nicely.
ActivatedRoute doesn't carry data, and here's the solution for detecting the page variable within the data: { page: 'login' }
.
import { Router, RoutesRecognized } from '@angular/router';
export class AppComponent {
page = '';
constructor(private router: Router) {
// listen to page variable from router events
router.events.subscribe(event => {
if (event instanceof RoutesRecognized) {
let route = event.state.root.firstChild;
this.page = 'page-' + route.data.page || '';
console.log('Page', this.page);
}
});
}
}
Solution 4:[4]
asmmahmud's Answer works well till Angular 5.x
but 6.X breaks the this.router.events
since rxjs 6.x has breaking changes. So just came across an update:
import {filter} from 'rxjs/operators';
import {map, mergeMap} from 'rxjs/internal/operators';
router.events
.pipe(filter(event => event instanceof NavigationEnd),
map(() => {
let route = activatedRoute.firstChild;
let child = route;
while (child) {
if (child.firstChild) {
child = child.firstChild;
route = child;
} else {
child = null;
}
}
return route;
}),
mergeMap(route => route.data)
)
.subscribe(data => {
console.log(data);
});
Solution 5:[5]
its work for component that not navigate (like header) :
this.route.root.firstChild.snapshot.data['title']
and complete example:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
export class HeaderComponent implements OnInit {
title: string;
constructor(private route: ActivatedRoute, private router: Router ) { }
ngOnInit() {
this.router.events.subscribe(event => {
if(event instanceof NavigationEnd) {
this.title = this.route.root.firstChild.snapshot.data['title']
}
});
}
}
cerdit to this answare
Solution 6:[6]
For those that are now using Angular 6+ and latest RXJS 6 here is something based on the ansers above:
Routing example:
const routes: Routes = [
{path: 'home', component: HomeComponent, data: {title: 'Home'}},
// {path: '', redirectTo: 'home', pathMatch: 'full'},
{path: 'login', component: LoginComponent, data: {title: 'Login'}},
{path: 'dashboard', component: DashboardComponent, data: {title: 'Dashboard'}, canActivate: [AppAuthGuard]},
{path: 'eventDetails', component: EventCardComponent, data: {title: 'Details'}},
{path: '**', redirectTo: 'home', pathMatch: 'full'},
];
How to get the title example:
ngOnInit() {
this.routerEventSubscription = this.router.events
.pipe(filter(event => event instanceof RoutesRecognized))
.pipe(map((event: RoutesRecognized) => {
return event.state.root.firstChild.data['title'];
})).subscribe(title => {
this.title = title;
});
}
Solution 7:[7]
if you want to have current route data, can get it from ActivatedRoute
public constructor(private activatedRoute:ActivatedRoute) {
console.log((activatedRoute.data as any).value);
}
Solution 8:[8]
2021
Research Router events for deeper knowledge on complex routing info.
But most of the time don't overthink it.
// 1. Subscribe in constructor to get events (OnInit and later are too late)
constructor(private router: Router) {
this.router.events.subscribe((event) => {
// 2. Start with ActivationEnd, experiment with the other events
if (event instanceof ActivationEnd) {
// 3. if your data exists assign it for use!
if (event.snapshot.data['searchSubject']) {
this.searchSubject = event.snapshot.data['searchSubject'];
}
}
});
Solution 9:[9]
You can subscribe to ActivatedRoute.data. This is somehow similar to the answer from @dinesh-kumar, but I believe (activatedRoute.data as any).value
is quite a hack taking advantage of the fact, that activatedRoute.data
is implemented as a BehaviorSubject. But the ActivatedRoute.data is exposed as Observable<Data>
, so the correct way would be to subscribe (don't forget to unsubscribe, or take(1)
etc.) or use async
pipe etc.
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data) => {
console.log(data);
});
}
Solution 10:[10]
After I tried a lot, I found the best solution
private ngUnsubscribe$ = new Subject();
constructor (private router: Router, private route: ActivatedRoute) { }
ngOnInit () {
const routeEndEvent$ = this.router.events
.pipe(
filter(e => e instanceof NavigationEnd),
tap(() => console.warn("END")),
);
this.router.events
.pipe(
filter(e => e instanceof ChildActivationEnd && e.snapshot.component === this.route.component),
buffer(routeEndEvent$),
map(([ev]) => (ev as ChildActivationEnd).snapshot.firstChild.data),
takeUntil(this.ngUnsubscribe$)
)
.subscribe(childRoute => {
console.log('childRoute', childRoute);
})
}
Solution 11:[11]
This worked for me in app.component.ts (ng 5)
constructor(
private router: Router,
) {
router.events.subscribe((routerEvent: Event) => {
this.checkRouterEvent(routerEvent);
});
}
checkRouterEvent(routerEvent: Event): void {
if (routerEvent instanceof ActivationStart) {
if (routerEvent.snapshot.data.custom_data) {
this.currentpage = routerEvent.snapshot.data['custom_data'];
console.log('4.' + this.currentpage);
}
}
Solution 12:[12]
this.router.events.subscribe((event: any) => {
this.pageTitle = this.titleService.getTitle();
// check instanceof ChildActivationEnd || ChildActivationStart
if (event instanceof ChildActivationStart) {
let pageIcon = event.snapshot?.firstChild?.children[0]?.data['icon'];
this.pageIcon = pageIcon ? pageIcon : this.pageIcon;
}
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow