fix(guards): Cancel in-flight guards if one returns false
This commit is contained in:
parent
6988a550ea
commit
97cf0e40d5
|
@ -1,6 +1,6 @@
|
||||||
import {Attribute, ComponentFactory, ComponentRef, Directive, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from "@angular/core";
|
import {Attribute, ComponentFactory, ComponentRef, Directive, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from '@angular/core';
|
||||||
import {RouterOutletMap} from "../router_outlet_map";
|
import {RouterOutletMap} from '../router_outlet_map';
|
||||||
import {PRIMARY_OUTLET} from "../shared";
|
import {PRIMARY_OUTLET} from '../shared';
|
||||||
|
|
||||||
@Directive({selector: 'router-outlet'})
|
@Directive({selector: 'router-outlet'})
|
||||||
export class RouterOutlet {
|
export class RouterOutlet {
|
||||||
|
|
|
@ -3,13 +3,15 @@ import 'rxjs/add/operator/scan';
|
||||||
import 'rxjs/add/operator/mergeMap';
|
import 'rxjs/add/operator/mergeMap';
|
||||||
import 'rxjs/add/operator/concat';
|
import 'rxjs/add/operator/concat';
|
||||||
import 'rxjs/add/operator/concatMap';
|
import 'rxjs/add/operator/concatMap';
|
||||||
|
import 'rxjs/add/operator/every';
|
||||||
|
import 'rxjs/add/operator/mergeAll';
|
||||||
|
import 'rxjs/add/observable/from';
|
||||||
|
|
||||||
import {Location} from '@angular/common';
|
import {Location} from '@angular/common';
|
||||||
import {ComponentResolver, Injector, ReflectiveInjector, Type} from '@angular/core';
|
import {ComponentResolver, Injector, ReflectiveInjector, Type} from '@angular/core';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import {Subject} from 'rxjs/Subject';
|
import {Subject} from 'rxjs/Subject';
|
||||||
import {Subscription} from 'rxjs/Subscription';
|
import {Subscription} from 'rxjs/Subscription';
|
||||||
import {forkJoin} from 'rxjs/observable/forkJoin';
|
|
||||||
import {of } from 'rxjs/observable/of';
|
import {of } from 'rxjs/observable/of';
|
||||||
|
|
||||||
import {RouterConfig} from './config';
|
import {RouterConfig} from './config';
|
||||||
|
@ -23,7 +25,7 @@ import {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot
|
||||||
import {PRIMARY_OUTLET, Params} from './shared';
|
import {PRIMARY_OUTLET, Params} from './shared';
|
||||||
import {UrlSerializer} from './url_serializer';
|
import {UrlSerializer} from './url_serializer';
|
||||||
import {UrlTree, createEmptyUrlTree} from './url_tree';
|
import {UrlTree, createEmptyUrlTree} from './url_tree';
|
||||||
import {and, forEach, shallowEqual} from './utils/collection';
|
import {forEach, shallowEqual} from './utils/collection';
|
||||||
import {TreeNode} from './utils/tree';
|
import {TreeNode} from './utils/tree';
|
||||||
|
|
||||||
export interface NavigationExtras {
|
export interface NavigationExtras {
|
||||||
|
@ -298,7 +300,8 @@ class GuardChecks {
|
||||||
const currRoot = this.curr ? this.curr._root : null;
|
const currRoot = this.curr ? this.curr._root : null;
|
||||||
this.traverseChildRoutes(futureRoot, currRoot, parentOutletMap);
|
this.traverseChildRoutes(futureRoot, currRoot, parentOutletMap);
|
||||||
if (this.checks.length === 0) return of (true);
|
if (this.checks.length === 0) return of (true);
|
||||||
return forkJoin(this.checks.map(s => {
|
return Observable.from(this.checks)
|
||||||
|
.map(s => {
|
||||||
if (s instanceof CanActivate) {
|
if (s instanceof CanActivate) {
|
||||||
return this.runCanActivate(s.route);
|
return this.runCanActivate(s.route);
|
||||||
} else if (s instanceof CanDeactivate) {
|
} else if (s instanceof CanDeactivate) {
|
||||||
|
@ -306,8 +309,9 @@ class GuardChecks {
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Cannot be reached');
|
throw new Error('Cannot be reached');
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
.map(and);
|
.mergeAll()
|
||||||
|
.every(result => result === true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private traverseChildRoutes(
|
private traverseChildRoutes(
|
||||||
|
@ -352,29 +356,33 @@ class GuardChecks {
|
||||||
private runCanActivate(future: ActivatedRouteSnapshot): Observable<boolean> {
|
private runCanActivate(future: ActivatedRouteSnapshot): Observable<boolean> {
|
||||||
const canActivate = future._routeConfig ? future._routeConfig.canActivate : null;
|
const canActivate = future._routeConfig ? future._routeConfig.canActivate : null;
|
||||||
if (!canActivate || canActivate.length === 0) return of (true);
|
if (!canActivate || canActivate.length === 0) return of (true);
|
||||||
return forkJoin(canActivate.map(c => {
|
return Observable.from(canActivate)
|
||||||
|
.map(c => {
|
||||||
const guard = this.injector.get(c);
|
const guard = this.injector.get(c);
|
||||||
if (guard.canActivate) {
|
if (guard.canActivate) {
|
||||||
return wrapIntoObservable(guard.canActivate(future, this.future));
|
return wrapIntoObservable(guard.canActivate(future, this.future));
|
||||||
} else {
|
} else {
|
||||||
return wrapIntoObservable(guard(future, this.future));
|
return wrapIntoObservable(guard(future, this.future));
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
.map(and);
|
.mergeAll()
|
||||||
|
.every(result => result === true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private runCanDeactivate(component: Object, curr: ActivatedRouteSnapshot): Observable<boolean> {
|
private runCanDeactivate(component: Object, curr: ActivatedRouteSnapshot): Observable<boolean> {
|
||||||
const canDeactivate = curr._routeConfig ? curr._routeConfig.canDeactivate : null;
|
const canDeactivate = curr._routeConfig ? curr._routeConfig.canDeactivate : null;
|
||||||
if (!canDeactivate || canDeactivate.length === 0) return of (true);
|
if (!canDeactivate || canDeactivate.length === 0) return of (true);
|
||||||
return forkJoin(canDeactivate.map(c => {
|
return Observable.from(canDeactivate)
|
||||||
|
.map(c => {
|
||||||
const guard = this.injector.get(c);
|
const guard = this.injector.get(c);
|
||||||
if (guard.canDeactivate) {
|
if (guard.canDeactivate) {
|
||||||
return wrapIntoObservable(guard.canDeactivate(component, curr, this.curr));
|
return wrapIntoObservable(guard.canDeactivate(component, curr, this.curr));
|
||||||
} else {
|
} else {
|
||||||
return wrapIntoObservable(guard(component, curr, this.curr));
|
return wrapIntoObservable(guard(component, curr, this.curr));
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
.map(and);
|
.mergeAll()
|
||||||
|
.every(result => result === true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue