web-dev-qa-db-fra.com

Comment obtenir tous les paramètres de route/données

Étant donné une configuration de route

{
   path: '/root/:rootId',
   children: [{
       path: '/child1/:child1Id',
       children: [{
           path: '/child2/:child2Id
           component: TestComponent
       }]
   }]
}

Dans TestComponent, comment puis-je obtenir facilement tous les paramètres de route. Je me demande s’il existe un moyen plus facile que

let rootId = route.parent.parent.snapshot.params;
let child1Id = route.parent.snapshot.params;
let child2Id = route.snapshot.params;

Cela semble excessivement redondant, surtout si je regarde les paramètres de route observables au lieu d’y accéder par le biais de la capture instantanée de route. Cette méthode semble également fragile, car elle casserait si je déplaçais n’importe laquelle des routes/paramètres. Je suis habitué au routeur ui angulaire où un seul objet $ stateParams était fourni avec toutes les données param facilement accessibles. J'ai les mêmes préoccupations concernant les données résolues par la route et l'accès à partir d'un seul nœud dans l'arbre de la route. Toute aide serait très appréciée. Merci d'avance

10
user2370392

À partir de Angular 5.2, vous pouvez configurer le routeur pour hériter de tous les paramètres en tant qu'enfants. Voir cet engagement si vous êtes intéressé par les détails sanglants, mais voici comment cela fonctionne pour moi:

Où que vous appeliez RouterModule.forRoot(), incluez un objet de configuration avec la stratégie d'héritage définie sur always (la valeur par défaut est emptyOnly):

import {RouterModule, ExtraOptions} from "@angular/router";

export const routingConfiguration: ExtraOptions = {
  paramsInheritanceStrategy: 'always'
};

export const Routing = RouterModule.forRoot(routes, routingConfiguration);

Désormais, lorsque vous êtes dans un composant enfant qui regarde une ActivatedRoute, les paramètres des ancêtres y apparaissent (par exemple, activatedRoute.params) plutôt que quelque chose de compliqué comme activatedRoute.parent.parent.parent.params. Vous pouvez accéder à la valeur directement (par exemple, activatedRoute.params.value.userId) ou vous abonner via activatedRoute.params.subscribe(...).

27
jmq

Vous devez itérer les segments de route.

Quelque chose comme

var params = [];
var route = router.routerState.snapshot.root;
do {
 params.Push(route.params); 
 route = route.firstChild;
} while(route);

Cela vous donne la liste de params de chaque segment de route, vous pouvez alors lire les valeurs param qui vous intéressent.

Object.keys(params) pourrait fonctionner pour obtenir tous les noms de paramètres disponibles à partir d'une instance param

3
Günter Zöchbauer

J'ai créé le service suivant pour pouvoir obtenir tous les paramètres de route en tant que ParamMap . L’idée principale est d’analyser récursivement tous les paramètres des routes enfants.

Github Gist

import {Injectable} from '@angular/core';
import {
  ActivatedRoute,
  Router,
  NavigationEnd,
  ParamMap,
  PRIMARY_OUTLET,
  RouterEvent
} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';

@Injectable()
export class ParamMapService {

  paramMap: Observable<ParamMap>;

  constructor(private router: Router,
              private route: ActivatedRoute) {
    this.paramMap = this.getParamMapObservable();
  }

  private getParamMap(route: ActivatedRoute): ParamMap {
    const map: Map<string, string | string[]> = new Map();

    while (route) {
      route.snapshot.paramMap.keys.forEach((key) => {
        map.set(key, this.getParamMapValue(route.snapshot.paramMap, key));
      });
      route = route.firstChild;
    }

    return <ParamMap>{
      keys: this.getParamMapKeys(map),
      has: this.getParamMapMethodHas(map),
      get: this.getParamMapMethodGet(map),
      getAll: this.getParamMapMethodGetAll(map)
    };
  }

  private getParamMapMethodGet(map: Map<string, string | string[]>): (name: string) => string | null {
    return (name: string): string | null => {
      const value = map.get(name);
      if (typeof value === 'string') {
        return value;
      }
      if (Array.isArray(value) && value.length) {
        return value[0];
      }
      return null;
    };
  }

  private getParamMapMethodGetAll(map: Map<string, string | string[]>): (name: string) => string[] {
    return (name: string): string[] => {
      const value = map.get(name);
      if (typeof value === 'string') {
        return [value];
      }
      if (Array.isArray(value)) {
        return value;
      }
      return [];
    };
  }

  private getParamMapMethodHas(map: Map<string, string | string[]>): (name: string) => boolean {
    return (name: string): boolean => map.has(name);
  }

  private getParamMapKeys(map: Map<string, string | string[]>): string[] {
    return Array.from(map.keys());
  }

  private getParamMapObservable(): Observable<ParamMap> {
    return this.router.events
      .filter((event: RouterEvent) => event instanceof NavigationEnd)
      .map(() => this.route)
      .filter((route: ActivatedRoute) => route.outlet === PRIMARY_OUTLET)
      .map((route: ActivatedRoute) => this.getParamMap(route));
  }

  private getParamMapValue(paramMap: ParamMap, key: string): string | string[] {
    return (paramMap.getAll(key).length > 1 ? paramMap.getAll(key) : paramMap.get(key));
  }
}

Exemple d'utilisation

id;

constructor(private paramMapService: ParamMapService) {
  this.paramMapService.paramMap.subscribe(paramMap => {
    this.id = paramMap.get('id');
  });
}

Remarque

ES6 Map est utilisé dans le service. Pour prendre en charge les anciens navigateurs, effectuez l’une des opérations suivantes:

  • Décommentez la ligne import 'core-js/es6/map'; dans polyfills.ts, ou
  • Convertissez toutes les occurrences de la carte en un objet simple.
0
m.spyratos
constructor(private route: ActivatedRoute) {}

data$ = of(this.route).pipe(
    expand(route => of(route['parent'])),
    takeWhile(route => !!route['parent']),
    pluck('snapshot', 'data'),
    reduce(merge));

Explication:

L'appel expand ici crée un observable pour chaque itinéraire de la chaîne parente. Takewhile est utilisé pour qu'il arrête de se répéter lorsque route ['parent'] renvoie la valeur null ou sur la route racine. 

Ensuite, pour toutes les routes de l'observable, Pluck mappera chacune d'elles sur sa propriété 'snapshot.data'. 

Enfin, réduire est alimenté la fonction de fusion de lodash pour combiner tous les objets de données en un seul objet. Ce flux regroupe toutes les données de la route en cours via les routes parentes

0
maburdi94

Angulaire 5:

import { combineLatest } from 'rxjs/observable/combineLatest';



 constructor(
    private activatedRoute: ActivatedRoute
  ) {
    combineLatest(
      this.activatedRoute.data,
      this.activatedRoute.params
    ).subscribe(([{from}, params]) => {
      this.params.from = from;
      this.params.id = params['id'];
      this.loadData();
    });
  }
0
Jimyx