web-dev-qa-db-fra.com

Paramètres angulaires 2 Activatedroute ne fonctionnant pas dans le service ou en dehors de <routeur-prise>

J'ai un problème très étrange: Index.html

<navigation-menu *ngIf="isLoggedIn"></navigation-menu>
<div class="content-wrapper" [ngClass]="{'fullContent' : !isLoggedIn}">
    <section class="content">
        <router-outlet></router-outlet>            
    </section>
</div>

Le menu de navigation est un composant du menu de navigation . Dans le contenu routeur-prise, il existe un composant appelé "actifs". 

Ce que j'ai fait dans le composant actif:

import { ActivatedRoute}from "@angular/router";
constructor(private route: ActivatedRoute){}
public ngOnInit(): void {
    this.route.params.subscribe(params => {
        const id = params["id"];
}

Cela fonctionne et j’obtiens les paramètres de mon itinéraire (ce qui est un peu "asset /: id).

Maintenant, j'ai essayé la même chose dans mon composant de menu de navigation (qui se trouve "à l'extérieur" de la sortie du routeur) et dans un service global appelé contextservice . Même code que ci-dessus, mais il n'est même pas déclenché lors du changement de route. Si j'essaie d'obtenir un instantané de routeur actuel 

  const strId = this.route.snapshot.params["id"];

après le déclenchement de l'événement NavigationEnd, le résultat est identique: strId n'est pas défini car les paramètres sont un objet vide.

Cela ne fonctionne que dans mon composant d'actif… .. Cela fonctionne-t-il comme prévu ou comment cela devrait-il être géré? 

Mon intention était de déclencher un événement à partir d'un service global (ou d'un composant "global" comme le menu de navigation) qui écoute toutes les modifications d'itinéraire (-params). 

Ma seule solution serait d'analyser l'URL complète après chaque événement NavigationEnd, ce qui, à mon avis, n'est pas approprié ... ou de gérer le changement des paramètres dans chaque composant enfant (dans le routeur-prise) lui-même.

Peut-être que j'ai juste une erreur de base dans la compréhension ...

Merci

Solution de réponse acceptée:

this.router.events.subscribe(val => {
        if (val instanceof RoutesRecognized) {
            var strId = val.state.root.firstChild.params["id"];
        }});

N'oubliez pas d'importer RoutesRecognized à partir d'un routeur angulaire !!

18
Cabe Skuriles

Le composant ajouté par le routeur obtient le segment du routeur (ActivatedRoute) transmis, mais dans un service, il n'y a pas de route activée. Vous pouvez vous abonner à router.events et parcourir l’arborescence des routes (router.firstChild ... `) pour obtenir les paramètres d’un séquencement de route spécifique.

Voir aussi https://github.com/angular/angular/issues/11023

18

Voici un service angulaire qui fait ça: 

import {Injectable}                                                        from '@angular/core';
import {ActivatedRoute, NavigationEnd, NavigationExtras, ParamMap, Router} from "@angular/router";
import {RouterExtensions}                                                  from "nativescript-angular/router";
import {NavigationOptions}                                                 from "nativescript-angular/router/ns-location-strategy";
import {Observable}                                                        from "rxjs/Observable";
import {first}                                                             from "rxjs/operators/first";
import {filter}                                                            from "rxjs/operators/filter";
import {map}                                                               from "rxjs/operators/map";
import {switchMap}                                                         from "rxjs/operators/switchMap";
import {unRegisterAndroidOnBack}                                           from "../../utils/view.utils";

@Injectable()
export class RoutingService
    {
        constructor(private routerExtensions: RouterExtensions, private route: ActivatedRoute, private router: Router)
        {
        }
        public getActivatedRouteParameter(paramName: string): Observable<ParamMap>
        {
            return this.router.events.pipe(filter(e => e instanceof NavigationEnd),
                                           map((): ActivatedRoute =>
                                               {
                                                   let route = this.route;
                                                   while (route.firstChild)
                                                       {
                                                           route = route.firstChild;
                                                       }
                                                   return route;
                                               }),
                                           filter((route: ActivatedRoute) => route.outlet === 'primary'),
                                           switchMap((route: ActivatedRoute) => route.paramMap) , first());

        }

.

1
Royi Namir

En fait, votre ActivéRoute est correct et mis à jour, mais vous avez tout l’arbre dans cela. donc si vous allez jusqu'au bout de route.firstChild, vous trouverez enfin le dernier itinéraire, que j'ai appelé deeperActivatedRoute (à l'intérieur de route.firstChild ... route.firstChild)

Alors ce que j’ai fait est de créer un service pour suivre deeperRoute, et de l’avoir toujours accessible 

import { Injectable } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';

@Injectable()
export class ActivatedRouteService {
  private _deeperActivatedRoute: ActivatedRoute;
  get deeperActivatedRoute(): ActivatedRoute {
    return this._deeperActivatedRoute;
  }

  constructor(private router: Router, private route: ActivatedRoute) {}

  init(): void {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        // Traverse the active route tree
        let activatedChild = this.route.firstChild;
        if (activatedChild != null) {
          let nextActivatedChild;
          while (nextActivatedChild != null) {
            nextActivatedChild = activatedChild.firstChild;
            if (nextActivatedChild != null) {
              activatedChild = activatedChild.firstChild;
            }
          }
        }

        this._deeperActivatedRoute = activatedChild || this.route;
      }
    });
  }
}

Ensuite, dans app.component.ts, je lance le service (juste pour m'assurer qu'il est toujours suivi)

export class AppComponent {
  constructor(private activatedRouteService: ActivatedRouteService) {
    this.activatedRouteService.init();
  }
}

Et enfin, prenez votre itinéraire, quel que soit le service que vous êtes:

export class ForbiddenInterceptor implements HttpInterceptor {
  constructor(private activatedRouteService: ActivatedRouteService) { }

  doYourStuff(): void {
       //you'll have the correct activatedRoute here
       this.activatedRouteService.deeperActivatedRoute;
  }
}

Pour répondre à la question, vous pouvez simplement prendre deeperActivatedRoute et vérifier normalement le fichier snapshop.url, comme vous le feriez dans un composant.

0
LuizAsFight