diff --git a/modules/@angular/router/src/config.ts b/modules/@angular/router/src/config.ts index 665c754bbc..25f926fb8f 100644 --- a/modules/@angular/router/src/config.ts +++ b/modules/@angular/router/src/config.ts @@ -242,7 +242,8 @@ export type RouterConfig = Route[]; * - `outlet` is the name of the outlet the component should be placed into. * - `canActivate` is an array of DI tokens used to look up CanActivate handlers. See {@link * CanActivate} for more info. - * - `canActivateChild` is an array of DI tokens used to look up CanActivateChild handlers. See {@link + * - `canActivateChild` is an array of DI tokens used to look up CanActivateChild handlers. See + * {@link * CanActivateChild} for more info. * - `canDeactivate` is an array of DI tokens used to look up CanDeactivate handlers. See {@link * CanDeactivate} for more info. diff --git a/modules/@angular/router/src/interfaces.ts b/modules/@angular/router/src/interfaces.ts index 05868f4d54..c9b7fe8e97 100644 --- a/modules/@angular/router/src/interfaces.ts +++ b/modules/@angular/router/src/interfaces.ts @@ -66,7 +66,8 @@ export interface CanActivate { * class CanActivateTeam implements CanActivate { * constructor(private permissions: Permissions, private currentUser: UserToken) {} * - * canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable { + * canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable + * { * return this.permissions.canActivate(this.currentUser, this.route.params.id); * } * } diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index 705938302b..94aac7b6c8 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -12,6 +12,7 @@ import 'rxjs/add/operator/mergeAll'; import 'rxjs/add/operator/reduce'; import 'rxjs/add/operator/every'; import 'rxjs/add/observable/from'; +import 'rxjs/add/observable/fromPromise'; import 'rxjs/add/observable/forkJoin'; import 'rxjs/add/observable/of'; @@ -596,6 +597,8 @@ class PreActivation { function wrapIntoObservable(value: T | Observable): Observable { if (value instanceof Observable) { return value; + } else if (value instanceof Promise) { + return Observable.fromPromise(value); } else { return Observable.of(value); } diff --git a/modules/@angular/router/test/router.spec.ts b/modules/@angular/router/test/router.spec.ts index 963a2233eb..90a05b6447 100644 --- a/modules/@angular/router/test/router.spec.ts +++ b/modules/@angular/router/test/router.spec.ts @@ -891,6 +891,40 @@ describe('Integration', () => { expect(location.path()).toEqual('/'); }))); }); + + describe('should work when returns a promise', () => { + beforeEach(() => { + addProviders([{ + provide: 'CanActivate', + useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + if (a.params['id'] == '22') { + return Promise.resolve(true); + } else { + return Promise.resolve(false); + } + } + }]); + }); + + + fit('works', + fakeAsync(inject( + [Router, TestComponentBuilder, Location], + (router: Router, tcb: TestComponentBuilder, location: Location) => { + const fixture = createRoot(tcb, router, RootCmp); + + router.resetConfig( + [{path: 'team/:id', component: TeamCmp, canActivate: ['CanActivate']}]); + + router.navigateByUrl('/team/22'); + advance(fixture); + expect(location.path()).toEqual('/team/22'); + + router.navigateByUrl('/team/33'); + advance(fixture); + expect(location.path()).toEqual('/team/22'); + }))); + }); }); describe('CanDeactivate', () => {