diff --git a/modules/@angular/router/src/directives/router_link.ts b/modules/@angular/router/src/directives/router_link.ts index a22737df2f..391cb1102e 100644 --- a/modules/@angular/router/src/directives/router_link.ts +++ b/modules/@angular/router/src/directives/router_link.ts @@ -1,5 +1,5 @@ -import {Directive, HostBinding, HostListener, Input, OnChanges} from '@angular/core'; import {LocationStrategy} from '@angular/common'; +import {Directive, HostBinding, HostListener, Input, OnChanges} from '@angular/core'; import {Router} from '../router'; import {ActivatedRoute} from '../router_state'; @@ -47,7 +47,9 @@ export class RouterLink implements OnChanges { /** * @internal */ - constructor(private router: Router, private route: ActivatedRoute, private locationStrategy: LocationStrategy) {} + constructor( + private router: Router, private route: ActivatedRoute, + private locationStrategy: LocationStrategy) {} @Input() set routerLink(data: any[]|string) { @@ -60,7 +62,7 @@ export class RouterLink implements OnChanges { ngOnChanges(changes: {}): any { this.updateTargetUrlAndHref(); } - @HostListener("click", ["$event.button", "$event.ctrlKey", "$event.metaKey"]) + @HostListener('click', ['$event.button', '$event.ctrlKey', '$event.metaKey']) onClick(button: number, ctrlKey: boolean, metaKey: boolean): boolean { if (button !== 0 || ctrlKey || metaKey) { return true; diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index 689a624a28..01d38a0ce0 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -345,6 +345,7 @@ class GuardChecks { const currRoot = this.curr ? this.curr._root : null; this.traverseChildRoutes(futureRoot, currRoot, parentOutletMap); if (this.checks.length === 0) return of (true); + return Observable.from(this.checks) .map(s => { if (s instanceof CanActivate) { diff --git a/modules/@angular/router/test/router.spec.ts b/modules/@angular/router/test/router.spec.ts index ee7560a372..13f2b23fcd 100644 --- a/modules/@angular/router/test/router.spec.ts +++ b/modules/@angular/router/test/router.spec.ts @@ -597,8 +597,11 @@ describe("Integration", () => { describe("CanDeactivate", () => { describe("should not deactivate a route when CanDeactivate returns false", () => { beforeEachProviders(() => [ - {provide: 'CanDeactivate', useValue: (c:TeamCmp, a:ActivatedRouteSnapshot, b:RouterStateSnapshot) => { + {provide: 'CanDeactivateTeam', useValue: (c:TeamCmp, a:ActivatedRouteSnapshot, b:RouterStateSnapshot) => { return c.route.snapshot.params['id'] === "22"; + }}, + {provide: 'CanDeactivateUser', useValue: (c:UserCmp, a:ActivatedRouteSnapshot, b:RouterStateSnapshot) => { + return a.params['name'] === 'victor'; }} ]); @@ -609,7 +612,7 @@ describe("Integration", () => { advance(fixture); router.resetConfig([ - { path: 'team/:id', component: TeamCmp, canDeactivate: ["CanDeactivate"] } + { path: 'team/:id', component: TeamCmp, canDeactivate: ["CanDeactivateTeam"] } ]); router.navigateByUrl('/team/22'); @@ -627,6 +630,35 @@ describe("Integration", () => { expect(location.path()).toEqual('/team/33'); }))); + + it('works with a nested route', + fakeAsync(inject([Router, TestComponentBuilder, Location], (router, tcb, location) => { + const fixture = tcb.createFakeAsync(RootCmp); + advance(fixture); + + router.resetConfig([ + { path: 'team/:id', component: TeamCmp, children: [ + {path: '/', terminal: true, component: SimpleCmp}, + {path: 'user/:name', component: UserCmp, canDeactivate: ["CanDeactivateUser"] } + ]} + ]); + + router.navigateByUrl('/team/22/user/victor'); + advance(fixture); + + // this works because we can deactivate victor + router.navigateByUrl('/team/33'); + advance(fixture); + expect(location.path()).toEqual('/team/33'); + + router.navigateByUrl('/team/33/user/fedor'); + advance(fixture); + + // this doesn't work cause we cannot deactivate fedor + router.navigateByUrl('/team/44'); + advance(fixture); + expect(location.path()).toEqual('/team/33/user/fedor'); + }))); }); describe("should work when given a class", () => {