Angular 2 router event listener

僤鯓⒐⒋嵵緔 提交于 2019-12-17 02:44:13

问题


How to listen state change in Angular 2 router?

In Angular 1.x I used this event:

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

So, if I use this eventlistener in Angular 2:

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

it isn't return 'ok', then change state from JS, only then browser history.back() function run.

Use router.subscribe() function as the 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');
        })
    }
}

Inject service in component which init in routing:

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) {}
}

I inject this service in other components such as in this example. Then I change state, console.info() in service not working.

What I do wrong?


回答1:


new router

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

old

Inject the Router and subscribe to route change events

import {Router} from 'angular2/router';

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

NOTE

For the new router, don't forget to import NavigationStart from router module

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

because if you don't import it instanceof will not work and an error NavigationStart is not defined will rise.

See also

  • https://angular.io/docs/ts/latest/api/router/index/Router-class.html
  • How to detect a route change in Angular 2?



回答2:


You can also filter events with filter().

But don't just use filter(e => e is NavigationEnd)

A much better solution is to add a 'type guard' to filter() like this:

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

It contains two things:

  • e is NavigationEnd this is the assertion you're defining a function for (this is typescript syntax)
  • e instanceof NavigationEnd this is the actual runtime code that checks the type

The nice thing with this is that operators further down 'the pipe', like map below now know the type is NavigationEnd, but without the type-guard you'd have a type Event.

If you only need to check for one event type then this is the cleanest way to do so. This also appears to be necessary in strict mode to avoid compiler errors.




回答3:


You can use instanceof as @GünterZöchbauer answered

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

or you can use a lazier approach, but remember constructor name can be changed easily while the function is still working!

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



回答4:


The angular 2 router events has different classes, and what gets passed to the subscription from the router.events observable can either be NavigationEnd, NavigationCancel, NavigationError, or NavigationStart. The one that will actually trigger a routing update will be NavigationEnd.

I would stay away from using instanceof or event.constructor.name because after minification the class names will get mangled it will not work correctly.

You can use the router's isActive function instead, shown here 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
  }
}



回答5:


in angular2, go to file "app.modules.ts"->imports

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

in enableTracing true show routeEvents in console in enableTracing false hide routeEvents in console




回答6:


import { Router,NavigationEnd  } from '@angular/router';
constructor(private route:Router){

  this.routeEvent(this.route);

}
routeEvent(router: Router){
  router.events.subscribe(e => {
    if(e instanceof NavigationEnd){
      console.log(e)
    }
  });
}



回答7:


To listen to all state changes, extend the default RouterOutlet and add your own logic in 'activate' and 'deactivate' handlers.

import {Directive} from 'angular2/core';
import {Router, RouterOutlet, ComponentInstruction} from 'angular2/router';

@Directive({
  selector: 'router-outlet'
})

export class MyOwnRouterOutlet extends RouterOutlet {
  ...

  activate() {
    console.log('Hello from the new router outlet!');
  }
}

Copied from 'Custom Router Outlet' example here: https://auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in-depth/



来源:https://stackoverflow.com/questions/35912932/angular-2-router-event-listener

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!