web-dev-qa-db-fra.com

Écouteur d'événement de routeur angulaire 2

Comment écouter le changement d'état dans le routeur angulaire 2?

Dans Angular 1.x, j'ai utilisé cet événement:

$rootScope.$on('$stateChangeStart',
    function(event,toState,toParams,fromState,fromParams, options){ ... })

Donc, si j'utilise cet eventlistener dans Angular 2:

window.addEventListener("hashchange", () => {return console.log('ok')}, false);

il n'est pas renvoyé 'ok', puis changez d'état à partir de JS, puis exécutez la fonction history.back () du navigateur.

Utilisez la fonction router.subscribe () en tant que service:

import {Injectable} from 'angular2/core';
import {Router} from 'angular2/router';

@Injectable()
export class SubscribeService {
    constructor (private _router: Router) {
        this._router.subscribe(val => {
            console.info(val, '<-- subscribe func');
        })
    }
}

Injecter le service dans le composant qui init in dans le routage:

import {Component} from 'angular2/core';
import {Router} from 'angular2/router';

@Component({
    selector: 'main',
    templateUrl: '../templates/main.html',
    providers: [SubscribeService]
})
export class MainComponent {
    constructor (private subscribeService: SubscribeService) {}
}

J'injecte ce service dans d'autres composants, comme dans cet exemple. Ensuite, je change d'état, console.info () dans le service ne fonctionne pas.

Ce que je fais mal?

53
Egor Medvedev

nouveau routeur

constructor(router:Router) {
  router.events.subscribe(event:Event => {
    if(event instanceof NavigationStart) {
    }
    // NavigationEnd
    // NavigationCancel
    // NavigationError
    // RoutesRecognized
  });
}

vieux

Injecter le routeur et s'abonner aux événements de changement d'itinéraire

import {Router} from 'angular2/router';

class MyComponent {
  constructor(router:Router) {
    router.subscribe(...)
  }
}

REMARQUE

Pour le nouveau routeur, n'oubliez pas d'importer le module NavigationStart à partir du module router

import { Router, NavigationStart } from '@angular/router';

parce que si vous ne l'importez pas, instanceof ne fonctionnera pas et une erreur NavigationStart is not defined augmentera.

Voir également 

119
Günter Zöchbauer

Vous pouvez utiliser instanceof comme @ GünterZöchbauer répondu

this.router.events.subscribe(event => {
  if(event instanceof NavigationStart) {
    // do something...
  }
}

ou vous pouvez utiliser une approchelazier, mais rappelez-vous que le nom du constructeur peut être changé facilement tant que la fonction est encore active!

this.router.events.subscribe(event => {
  if(event.constructor.name === "NavigationStart") {
    // do something...
  }
});
4
Khaled Al-Ansari

Vous pouvez également filtrer les événements avec filter()

Mais n'utilisez pas seulementfilter(e => e is NavigationEnd)

Une solution bien meilleure consiste à ajouter un "garde de type" à filter() comme ceci:

 filter((e): e is NavigationEnd => e instanceof NavigationEnd), 

Il contient deux choses:

  • e is NavigationEnd c'est l'assertion pour laquelle vous définissez une fonction (c'est la syntaxe TypeScript)
  • e instanceof NavigationEnd c'est le code d'exécution réel qui vérifie le type

La bonne chose à cela est que les opérateurs plus bas dans le tuyau, comme map ci-dessous savent maintenant que le type est NavigationEnd, mais sans le type-guard vous auriez un type Event.

Si vous ne devez rechercher qu'un seul type d'événement, c'est la manière la plus propre de le faire. Cela semble également être nécessaire en mode strict pour éviter les erreurs de compilation.

 enter image description here

2
Simon_Weaver

dans angular2, allez dans le fichier "app.modules.ts" -> importations

RouterModule.forRoot(
      appRoutes,
      { 
         enableTracing: true
      }
)

dans enableTracing true Voir routeEvents dans consolein enableTracing false masquer RouteEvents dans console

Les événements de routeur angulaires 2 ont différentes classes et ce qui est transmis à l'abonnement depuis l'observable router.events peut être NavigationEnd, NavigationCancel, NavigationError ou NavigationStart. Celui qui déclenchera réellement une mise à jour de routage sera NavigationEnd.

Je voudrais éviter d'utiliser instanceof ou event.constructor.name car après minification, les noms de classe seront mutilés, cela ne fonctionnera pas correctement.

Vous pouvez utiliser la fonction isActive du routeur à la place, comme indiqué ici https://angular.io/docs/ts/latest/api/router/index/Router-class.html

this.routerEventSubscription = this._router.events.subscribe((event: any) => {
  if (this._router.isActive(events.url, false)) { 
    // true if the url route is active
  }
}
0
Y. Brahimi