From 777eb2f1599ae713eea19c8a74388eb15950a15a Mon Sep 17 00:00:00 2001 From: vsavkin Date: Thu, 9 Jun 2016 14:31:49 -0700 Subject: [PATCH] feat(router): emit an event when routes are recognized --- .../router/src/common_router_providers.ts | 15 ++++++++++++++- modules/@angular/router/src/index.ts | 2 +- modules/@angular/router/src/router.ts | 8 ++++++++ modules/@angular/router/test/router.spec.ts | 10 +++++++--- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/modules/@angular/router/src/common_router_providers.ts b/modules/@angular/router/src/common_router_providers.ts index b59a27ceca..55e723b4c5 100644 --- a/modules/@angular/router/src/common_router_providers.ts +++ b/modules/@angular/router/src/common_router_providers.ts @@ -7,6 +7,9 @@ import {RouterOutletMap} from './router_outlet_map'; import {ActivatedRoute} from './router_state'; import {DefaultUrlSerializer, UrlSerializer} from './url_serializer'; +export interface ExtraOptions { + enableTracing?: boolean; +} /** * A list of {@link Provider}s. To use the router, you must add this to your application. @@ -26,7 +29,7 @@ import {DefaultUrlSerializer, UrlSerializer} from './url_serializer'; * bootstrap(AppCmp, [provideRouter(router)]); * ``` */ -export function provideRouter(config: RouterConfig): any[] { +export function provideRouter(config: RouterConfig, opts: ExtraOptions): any[] { return [ Location, {provide: LocationStrategy, useClass: PathLocationStrategy}, @@ -42,6 +45,16 @@ export function provideRouter(config: RouterConfig): any[] { const r = new Router( componentType, resolver, urlSerializer, outletMap, location, injector, config); ref.registerDisposeListener(() => r.dispose()); + + if (opts.enableTracing) { + r.events.subscribe(e => { + console.group(`Router Event: ${(e.constructor).name}`); + console.log(e.toString()); + console.log(e); + console.groupEnd(); + }); + } + return r; }, deps: diff --git a/modules/@angular/router/src/index.ts b/modules/@angular/router/src/index.ts index 95c089547b..24e70a2352 100644 --- a/modules/@angular/router/src/index.ts +++ b/modules/@angular/router/src/index.ts @@ -3,7 +3,7 @@ import {RouterOutlet} from './directives/router_outlet'; export {Route, RouterConfig} from './config'; export {CanActivate, CanDeactivate} from './interfaces'; -export {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router} from './router'; +export {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, RoutesRecognized, Router} from './router'; export {RouterOutletMap} from './router_outlet_map'; export {provideRouter} from './router_providers'; export {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot} from './router_state'; diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index 266d9dd4fa..ad87fec116 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -63,6 +63,13 @@ export class NavigationError { constructor(public id: number, public url: UrlTree, public error: any) {} } +/** + * An event triggered when routes are recognized + */ +export class RoutesRecognized { + constructor(public id: number, public url: UrlTree, public urlAfterRedirects: UrlTree, public state: RouterStateSnapshot) {} +} + export type Event = NavigationStart | NavigationEnd | NavigationCancel | NavigationError; /** @@ -246,6 +253,7 @@ export class Router { }) .mergeMap((newRouterStateSnapshot) => { + this.routerEvents.next(new RoutesRecognized(id, url, updatedUrl, newRouterStateSnapshot)); return resolve(this.resolver, newRouterStateSnapshot); }) diff --git a/modules/@angular/router/test/router.spec.ts b/modules/@angular/router/test/router.spec.ts index 2dfe268e4c..40ff2aecd5 100644 --- a/modules/@angular/router/test/router.spec.ts +++ b/modules/@angular/router/test/router.spec.ts @@ -18,7 +18,7 @@ import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing' import { ComponentResolver } from '@angular/core'; import { SpyLocation } from '@angular/common/testing'; import { UrlSerializer, DefaultUrlSerializer, RouterOutletMap, Router, ActivatedRoute, ROUTER_DIRECTIVES, Params, - RouterStateSnapshot, ActivatedRouteSnapshot, CanActivate, CanDeactivate, Event, NavigationStart, NavigationEnd, NavigationCancel, NavigationError, RouterConfig } from '../src/index'; + RouterStateSnapshot, ActivatedRouteSnapshot, CanActivate, CanDeactivate, Event, NavigationStart, NavigationEnd, NavigationCancel, NavigationError, RoutesRecognized, RouterConfig } from '../src/index'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import {of} from 'rxjs/observable/of'; @@ -269,14 +269,16 @@ describe("Integration", () => { expect(fixture.debugElement.nativeElement).toHaveText('user fedor'); expect(user.recordedParams).toEqual([{name: 'init'}, {name: 'fedor'}]); - expectEvents(router, recordedEvents.slice(1), [ + expectEvents(router, recordedEvents.slice(2), [ [NavigationStart, '/user/init'], + [RoutesRecognized, '/user/init'], [NavigationEnd, '/user/init'], [NavigationStart, '/user/victor'], [NavigationStart, '/user/fedor'], [NavigationCancel, '/user/victor'], + [RoutesRecognized, '/user/fedor'], [NavigationEnd, '/user/fedor'] ]); }))); @@ -302,11 +304,13 @@ describe("Integration", () => { advance(fixture); expect(fixture.debugElement.nativeElement).toHaveText('user fedor'); - expectEvents(router, recordedEvents.slice(1), [ + + expectEvents(router, recordedEvents.slice(2), [ [NavigationStart, '/invalid'], [NavigationError, '/invalid'], [NavigationStart, '/user/fedor'], + [RoutesRecognized, '/user/fedor'], [NavigationEnd, '/user/fedor'] ]); })));