Dans la dernière version de @angular/router
3.0.0-rc.1
La façon dont vous obtenez les paramètres depuis une URL/une route a été modifiée.
Basé sur this documentation, vous devriez pouvoir obtenir les paramètres en vous abonnant, mais dans mon cas, il semble que cela ne fonctionne pas.
Ce que je veux réaliser est d’obtenir des paramètres dans mon composant parent FROM routes enfants.
Par exemple, disons que ce sont mes routes:
const routes: Routes = [
{
path: 'parent',
component: ParentComponent,
pathMatch: 'prefix',
children: [
{
path: ':id',
component: ChildComponent
}
]
}
];
Je veux obtenir le paramètre id
et l'utiliser dans mon ParentComponent . Donc j'essaie comme ceci:
export class ParentComponent implements OnInit {
sub: any;
constructor(
private route: ActivatedRoute) {
this.route = route;
}
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = params['id'];
console.log(id);
});
}
}
Comme ça j'obtiens:
Undefined
Qu'est-ce que j'oublie ici?
La ActivatedRoute
a des accesseurs pour accéder aux informations sur son itinéraire parent/enfant.
Pour accéder au premier itinéraire enfant à partir du parent, vous utiliseriez:
this.route.firstChild.params
Si vous vouliez tous les itinéraires enfants, vous utiliseriez la propriété children
. Ceci retourne un tableau de ActivatedRoute
this.route.children
Si vous étiez dans une route enfant et que vous aviez besoin des paramètres du parent:
this.route.parent.params
Les paramètres enfants sont associés/enregistrés avec l'enfant ActivatedRoute . Ils ne sont pas disponibles sur ActivatedRoute du parent. Vous devez donc d'abord obtenir ActivatedRoute de l'enfant avec getter firstChild
ou children
.
Ensuite, le parent peut s’abonner aux modifications apportées aux paramètres enfants:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
export class ParentComponent implements OnInit, OnDestroy {
private sub: Subscription;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.sub = this.route.firstChild.params.subscribe(
params => console.log(params.id));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
ou il peut obtenir un instantané des paramètres enfants:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
export class ParentComponent {
constructor(private route: ActivatedRoute) {}
someMethod() {
console.log(this.route.firstChild.snapshot.params.id);
}
}
Si vous souhaitez obtenir tous les enfants (par exemple, si vous avez plusieurs points de vente), utilisez ActivatedRoute.children
ou ActivatedRouteSnapshot.children
pour obtenir un tableau d'enfants ActivatedRoutes ou ActivatedRouteShapshots.
this.route.snapshot.paramMap.get('id');
this.router.events.subscribe(event => {
if (event instanceof RoutesRecognized) {
// let strId = event.state.root.firstChild.children[0].data;
let a = event.state.root.firstChild.children.map((route) => {
while (route.firstChild) {
route = route.firstChild;
}
return route;
});
console.log('Title', a[0].data.title);
this.meta.updateTitle(a[0].data.title);
}
if (event instanceof NavigationEnd) {
(<any>window).gtag('config', this.googleAnalyticsCode, {
'page_title' : this.titleService.getTitle(),
'page_path': event.urlAfterRedirects
});
}
});
En utilisant this.activatedRoute.snapshot.firstChild.params
Il est très facile d'obtenir les paramètres enfants via ActivatedRoute. Toutefois, vous pouvez rapidement rencontrer des problèmes si vous modifiez l'enfant actuel.
D'abord quelques notes:
activatedRoute.firstChild
est une instance ActivatedRoute
et PAS une observable.activatedRoute.paramMap
est un observable.Voici comment vous pouvez rencontrer des problèmes:
firstChild.paramMap
dans votre gestionnaire ngOnInit
, vous pourrez vous y abonner et surveiller les paramètres à mesure qu'ils changent. Cela va regarder et fonctionne très bien.paramMap
sur une instance ActivatedRoute qui n'existe plus.paramMap
de l'enfant. Si vous essayez d'accéder à votre "propre" paramMap, ou si le composant enfant injecte également paramMap
, tout ira bien.La solution la plus propre à ce que j'ai trouvée est la suivante:
Remarque: Commencez par injecter router: Router
en plus de route: ActivatedRoute
.
const firstChildParams$ = this.router.events.pipe(filter(e => e instanceof NavigationEnd),
startWith(undefined),
switchMap(e => this.route.firstChild!.paramMap));
Cela n'écoute que les événements NavigationEnd, après quoi une nouvelle firstChild
sera disponible. En utilisant switchMap
, vous n'avez pas à craindre de vous désabonner des anciennes cartes redondantes. De même, la valeur réelle de l'événement de navigation n'est jamais utilisée, et startWith
est nécessaire pour pouvoir gérer les paramètres immédiatement la première fois.
J'ai rassemblé des choses utiles comme celle-ci dans un RouterHelperService que je peux injecter n'importe où, sans avoir à me souvenir de toute cette folie.
Un jour, je pourrais suggérer qu'il devrait y avoir un équivalent observable de firstChild
, alors ce ne serait pas un problème. Cependant, cela introduirait peut-être encore plus de confusion dans d'autres scénarios!