I have a main component that has a router-outlet in it. In the component that is loaded in the router-outlet I grab the url parameter like this:
ngOnInit(): void {
// _route is injected ActivatedRoute
this._route.params.subscribe((params: Params) => {
if(params['url']){
this.testUrl = params['url'].replace(new RegExp('\%2[fF]', 'g'), '/');
}
});
}
This works fine, but when I try it on my top level component the params object is always empty. I don't understand why as the nested components param object has the data in it and I am trying to access it exactly the same way. There are no errors to go on, the param object is just empty.
Why doesn't my parent component get the right Params object from ActivatedRoute?
edit:
as requested full parent component
import { OnInit, Component, Directive } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
})
export class AppComponent {
public testUrl: string;
constructor(private router: Router, private _route: ActivatedRoute) {
}
ngOnInit(): void{
this._route.queryParams.subscribe((params: Params) => {
console.log(params);
if (params['url']) {
this.testUrl = params['url'].replace(new RegExp('\%2[fF]', 'g'), '/');
alert(params['url']);
}
});
}
}
router code for app.module.ts:
RouterModule.forRoot([
{ path: '', component: CheckMobileComponent },
{ path: '**', component: CheckMobileComponent }
]),
router code for nested module:
RouterModule.forChild([
{ path: 'report', component: MobileReportComponent }
There is no directly specified route for my app.component as it is loaded by a selector in index.html.
ActivatedRoute
: Contains the information about a route associated with a component loaded in an router outlet. If you would like to access route details outside of it, use the code below.
import { Component } from '@angular/core';
import { Router, ActivatedRoute, Params, RoutesRecognized } from '@angular/router';
export class AppComponent {
constructor(private route: ActivatedRoute, private router: Router) {
}
ngOnInit(): void {
this.router.events.subscribe(val => {
if (val instanceof RoutesRecognized) {
console.log(val.state.root.firstChild.params);
}
});
}
}
There are other ways to share data in between components for example by using a service.
For more details about how you can tackle this as concept, read comments here.
The Very simple answer
import { Component } from '@angular/core';
import { Router, ActivatedRoute, Params, RoutesRecognized } from
'@angular/router';
export class AppComponent {
constructor(private actRoute: ActivatedRoute, private router:
Router){}
ngOnInit(): void {
this.actRoute.firstChild.params.subscribe(
(params: any) => {
if (params.hasOwnProperty('<whatever the param name>') != '') {
//do whatever you want
console.log(params.<whatever the param name>);
}
}
});
}
}
ActivatedRoute
works for components loaded via router-outlet
. From docs - it:
Contains the information about a route associated with a component loaded in an outlet.
I don't think you can use it in components that are not loaded in an outlet. It also doesn't work in base classes your component extends.
class A { constructor(public route: ActivatedRoute) }
class B extends A { ngOnInit() { this.route; } } // not working
class C { constructor(public route: ActivatedRoute) } // working if loaded in outlet
I was having a very similar problem with this mainly due to my misunderstanding of how routes actually worked. I thought I could just go up the chain of path parameters and each one would be a parent/child relationship. However, if a route has more than one element to the path, (e.g. /dashboard
and profile/:user_id
) it will depend on how you set up the routes in your routing module(s).
To explain a different way that made it click for me:
// If I am trying to access ActivatedRoute from the CheckMobileComponent (say
// through a `router-outlet`), I could get it through something like
// `this._route.firstChild`
{ path: '', component: CheckMobileComponent, children: [
// If I want to get things from the '' context in MobileReportComponent, it
// would be through something like `this._route.parent`
{ path: 'report', component: MobileReportComponent }
]
}
If you'd like to access the router parameters via a service, this approach will not work! consider using a service to prevent the replication of the "Route params value extraction logic" (from this Medium article):
@Injectable({
providedIn: 'root'
})
export class MyParamsAwareService {
constructor(private router: Router) {
this.router.events
.pipe(
filter(e => (e instanceof ActivationEnd) && (Object.keys(e.snapshot.params).length > 0)),
map(e => e instanceof ActivationEnd ? e.snapshot.params : {})
)
.subscribe(params => {
console.log(params);
// Do whatever you want here!!!!
});
}
}