diff --git a/packages/router/src/operators/resolve_data.ts b/packages/router/src/operators/resolve_data.ts new file mode 100644 index 0000000000..0f760bf800 --- /dev/null +++ b/packages/router/src/operators/resolve_data.ts @@ -0,0 +1,28 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Injector, Type} from '@angular/core'; +import {Observable, OperatorFunction} from 'rxjs'; +import {mergeMap} from 'rxjs/operators'; + +import {Route} from '../config'; +import {PreActivation} from '../pre_activation'; +import {recognize as recognizeFn} from '../recognize'; +import {ChildrenOutletContexts} from '../router_outlet_context'; +import {RouterStateSnapshot} from '../router_state'; +import {UrlTree} from '../url_tree'; + +export function resolveData( + preActivation: PreActivation, + paramsInheritanceStrategy: 'emptyOnly' | 'always'): OperatorFunction { + return function(source: Observable) { + return source.pipe(mergeMap((appliedUrl): Observable => { + return preActivation.resolveData(paramsInheritanceStrategy); + })); + }; +} \ No newline at end of file diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 358b6d359b..087c1b66cb 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -19,6 +19,7 @@ import {applyRedirects} from './operators/apply_redirects'; import {beforePreactivation} from './operators/before_preactivation'; import {checkGuards} from './operators/check_guards'; import {recognize} from './operators/recognize'; +import {resolveData} from './operators/resolve_data'; import {setupPreactivation} from './operators/setup_preactivation'; import {PreActivation} from './pre_activation'; import {DefaultRouteReuseStrategy, DetachedRouteHandleInternal, RouteReuseStrategy} from './route_reuse_strategy'; @@ -730,39 +731,43 @@ export class Router { const preactivationCheckGuards$: Observable = preactivationSetup$.pipe(mergeMap( - p => this.navigationId !== id ? of (false) : of (p.appliedUrl) - .pipe( - tap(_ => this.triggerEvent(new GuardsCheckStart( - id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), - p.snapshot))), - checkGuards( - this.rootContexts, this.routerState.snapshot, this.ngModule.injector, - preActivation), - tap(shouldActivate => this.triggerEvent(new GuardsCheckEnd( - id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), - p.snapshot, shouldActivate))), - map(shouldActivate => ({ - appliedUrl: p.appliedUrl, - snapshot: p.snapshot, - shouldActivate: shouldActivate - }))))); + p => this.navigationId !== id ? + of (false) : + of (p.appliedUrl) + .pipe( + tap(_ => this.triggerEvent(new GuardsCheckStart( + id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), + p.snapshot))), + checkGuards( + this.rootContexts, this.routerState.snapshot, this.ngModule.injector, + preActivation), + tap(shouldActivate => this.triggerEvent(new GuardsCheckEnd( + id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), + p.snapshot, shouldActivate))), + map(shouldActivate => ({ + appliedUrl: p.appliedUrl, + snapshot: p.snapshot, + shouldActivate: shouldActivate + }))))); - const preactivationResolveData$ = - preactivationCheckGuards$.pipe(mergeMap((p): Observable => { - if (typeof p === 'boolean' || this.navigationId !== id) return of (false); - - if (p.shouldActivate && preActivation.isActivating()) { - this.triggerEvent(new ResolveStart( - id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), p.snapshot)); - return preActivation.resolveData(this.paramsInheritanceStrategy).pipe(map(() => { - this.triggerEvent(new ResolveEnd( - id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), p.snapshot)); - return p; - })); - } else { - return of (p); - } - })); + const preactivationResolveData$: Observable = preactivationCheckGuards$.pipe(mergeMap(p => + // TODO(jasonaden): This should be simplified so there's one route to cancelling navigation, which would + // unravel the stream. This would get rid of all these imperative checks in the middle of navigation. + typeof p === 'boolean' || this.navigationId !== id ? + of (false) : + p.shouldActivate && preActivation.isActivating() ? + of (p.appliedUrl) + .pipe( + tap(_ => this.triggerEvent(new ResolveStart( + id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), + p.snapshot))), + resolveData(preActivation, this.paramsInheritanceStrategy), + tap(_ => this.triggerEvent(new ResolveEnd( + id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), + p.snapshot))), + map(_ => p)) : + of (p) + )); const preactivationDone$ = preactivationResolveData$.pipe(mergeMap((p): Observable => {