Skip to content

Commit 97cf0e4

Browse files
MikeRyanDevvsavkin
authored andcommitted
fix(guards): Cancel in-flight guards if one returns false
1 parent 6988a55 commit 97cf0e4

File tree

2 files changed

+41
-33
lines changed

2 files changed

+41
-33
lines changed

modules/@angular/router/src/directives/router_outlet.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import {Attribute, ComponentFactory, ComponentRef, Directive, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from "@angular/core";
2-
import {RouterOutletMap} from "../router_outlet_map";
3-
import {PRIMARY_OUTLET} from "../shared";
1+
import {Attribute, ComponentFactory, ComponentRef, Directive, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from '@angular/core';
2+
import {RouterOutletMap} from '../router_outlet_map';
3+
import {PRIMARY_OUTLET} from '../shared';
44

55
@Directive({selector: 'router-outlet'})
66
export class RouterOutlet {

modules/@angular/router/src/router.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import 'rxjs/add/operator/scan';
33
import 'rxjs/add/operator/mergeMap';
44
import 'rxjs/add/operator/concat';
55
import 'rxjs/add/operator/concatMap';
6+
import 'rxjs/add/operator/every';
7+
import 'rxjs/add/operator/mergeAll';
8+
import 'rxjs/add/observable/from';
69

710
import {Location} from '@angular/common';
811
import {ComponentResolver, Injector, ReflectiveInjector, Type} from '@angular/core';
912
import {Observable} from 'rxjs/Observable';
1013
import {Subject} from 'rxjs/Subject';
1114
import {Subscription} from 'rxjs/Subscription';
12-
import {forkJoin} from 'rxjs/observable/forkJoin';
1315
import {of } from 'rxjs/observable/of';
1416

1517
import {RouterConfig} from './config';
@@ -23,7 +25,7 @@ import {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot
2325
import {PRIMARY_OUTLET, Params} from './shared';
2426
import {UrlSerializer} from './url_serializer';
2527
import {UrlTree, createEmptyUrlTree} from './url_tree';
26-
import {and, forEach, shallowEqual} from './utils/collection';
28+
import {forEach, shallowEqual} from './utils/collection';
2729
import {TreeNode} from './utils/tree';
2830

2931
export interface NavigationExtras {
@@ -298,16 +300,18 @@ class GuardChecks {
298300
const currRoot = this.curr ? this.curr._root : null;
299301
this.traverseChildRoutes(futureRoot, currRoot, parentOutletMap);
300302
if (this.checks.length === 0) return of (true);
301-
return forkJoin(this.checks.map(s => {
302-
if (s instanceof CanActivate) {
303-
return this.runCanActivate(s.route);
304-
} else if (s instanceof CanDeactivate) {
305-
return this.runCanDeactivate(s.component, s.route);
306-
} else {
307-
throw new Error('Cannot be reached');
308-
}
309-
}))
310-
.map(and);
303+
return Observable.from(this.checks)
304+
.map(s => {
305+
if (s instanceof CanActivate) {
306+
return this.runCanActivate(s.route);
307+
} else if (s instanceof CanDeactivate) {
308+
return this.runCanDeactivate(s.component, s.route);
309+
} else {
310+
throw new Error('Cannot be reached');
311+
}
312+
})
313+
.mergeAll()
314+
.every(result => result === true);
311315
}
312316

313317
private traverseChildRoutes(
@@ -352,29 +356,33 @@ class GuardChecks {
352356
private runCanActivate(future: ActivatedRouteSnapshot): Observable<boolean> {
353357
const canActivate = future._routeConfig ? future._routeConfig.canActivate : null;
354358
if (!canActivate || canActivate.length === 0) return of (true);
355-
return forkJoin(canActivate.map(c => {
356-
const guard = this.injector.get(c);
357-
if (guard.canActivate) {
358-
return wrapIntoObservable(guard.canActivate(future, this.future));
359-
} else {
360-
return wrapIntoObservable(guard(future, this.future));
361-
}
362-
}))
363-
.map(and);
359+
return Observable.from(canActivate)
360+
.map(c => {
361+
const guard = this.injector.get(c);
362+
if (guard.canActivate) {
363+
return wrapIntoObservable(guard.canActivate(future, this.future));
364+
} else {
365+
return wrapIntoObservable(guard(future, this.future));
366+
}
367+
})
368+
.mergeAll()
369+
.every(result => result === true);
364370
}
365371

366372
private runCanDeactivate(component: Object, curr: ActivatedRouteSnapshot): Observable<boolean> {
367373
const canDeactivate = curr._routeConfig ? curr._routeConfig.canDeactivate : null;
368374
if (!canDeactivate || canDeactivate.length === 0) return of (true);
369-
return forkJoin(canDeactivate.map(c => {
370-
const guard = this.injector.get(c);
371-
if (guard.canDeactivate) {
372-
return wrapIntoObservable(guard.canDeactivate(component, curr, this.curr));
373-
} else {
374-
return wrapIntoObservable(guard(component, curr, this.curr));
375-
}
376-
}))
377-
.map(and);
375+
return Observable.from(canDeactivate)
376+
.map(c => {
377+
const guard = this.injector.get(c);
378+
if (guard.canDeactivate) {
379+
return wrapIntoObservable(guard.canDeactivate(component, curr, this.curr));
380+
} else {
381+
return wrapIntoObservable(guard(component, curr, this.curr));
382+
}
383+
})
384+
.mergeAll()
385+
.every(result => result === true);
378386
}
379387
}
380388

0 commit comments

Comments
 (0)