I need to get param from route which is not parent and not even grand-parent, it's simply somewhere above, along the path to root. I am aware of approaches like shown in Angular 2: getting RouteParams from parent component or through shared service but situation which I put myself into (at least I think so) makes those not well suited for it. So here is what I got:
I have lazily loaded sub-module which needs id
from parent context. Situation more or less looks in routing configuration like this :
// Parent/outer module routing
const outerRoutes: Routes = [
{
path: 'container/:containerId',
component: ContainerComponent,
children: [
{ path: 'model', loadChildren: 'app/container/model/model.module#ModelModule' },
{ path: '', component: ContainerDetailsComponent }
]
}
];
// Child/inner module routing
const innerRoutes: Routes = [
{
path: '',
component: ModelComponent,
children: [
{ path: ':id', component: ModelDetailsComponent },
{ path: '', component: ModelsComponent }
]
}
];
ModelsComponent
needs to load all Model
instances belonging to given Container
. So I decided to go through .parent
approach but my teeth started to hurt after writing 2nd .parent
and there was still 3rd to come:
this.route.parent.parent.parent.params
.switchMap((params: Params) => this.modelService.getAllBelongingTo(params['containerId']))
.subscribe(
(models: Model[]) => this.models = models,
error => this.raceEvent = null
);
Shared service is somehow an option but due to the fact that child module is lazily loaded I would have to put it in core module making it quite global (which I don't like).
After a bit of struggling I came to following piece of code, which simply takes all ActivatedRoute
up to the root, combines them, does lookup for param and consumes it. I don't like it as in my opinion it too complex , unreadable and stinks from a mile (or in other words is gory as heck) but works and I don't have to take care whether nesting changes. I simply have to make sure that :containerId
is somewhere up there on the path to root.
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Model } from './model';
import { ModelService } from './model.service';
@Component({
...
})
export class ModelsComponent implements OnInit {
models: Model[];
constructor(
private route: ActivatedRoute,
private modelService: ModelService) { }
ngOnInit() {
const paramsArr = this.route.pathFromRoot.map(route => route.params);
Observable.combineLatest(paramsArr)
.switchMap(arrOfParams => {
const params = arrOfParams.find(p => p['containerId'] !== undefined),
id = params && params['containerId'];
return id ? this.modelService.getAllBelongingTo(id) : [];
})
.subscribe(
(models: Model[]) => {
// yay! we got sth
this.models = models;
},
error => {
// handle big nono
}
);
}
}
Is there a better way to handle depicted situation?