From 4fe39e3b37a150e945c28cddffc9a1c297dd0eb6 Mon Sep 17 00:00:00 2001 From: Chris Thielen Date: Thu, 5 Jan 2017 10:17:25 -0600 Subject: [PATCH] feat(Transition): Add Transition.originalTransition() to return the initial transition in a chain of redirects --- src/hooks/lazyLoad.ts | 8 +++----- src/transition/transition.ts | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/hooks/lazyLoad.ts b/src/hooks/lazyLoad.ts index 51b1614d..1c761b64 100644 --- a/src/hooks/lazyLoad.ts +++ b/src/hooks/lazyLoad.ts @@ -32,12 +32,10 @@ import { StateRule } from "../url/interface"; * See [[StateDeclaration.lazyLoad]] */ const lazyLoadHook: TransitionHookFn = (transition: Transition) => { - const transitionSource = (trans: Transition) => - trans.redirectedFrom() ? transitionSource(trans.redirectedFrom()) : trans.options().source; let router = transition.router; - function retryOriginalTransition() { - if (transitionSource(transition) !== 'url') { + function retryTransition() { + if (transition.originalTransition().options().source !== 'url') { // The original transition was not triggered via url sync // The lazy state should be loaded now, so re-try the original transition let orig = transition.targetState(); @@ -66,7 +64,7 @@ const lazyLoadHook: TransitionHookFn = (transition: Transition) => { .filter(state => !!state.lazyLoad) .map(state => lazyLoadState(transition, state)); - return services.$q.all(promises).then(retryOriginalTransition); + return services.$q.all(promises).then(retryTransition); }; export const registerLazyLoadHook = (transitionService: TransitionService) => diff --git a/src/transition/transition.ts b/src/transition/transition.ts index 05b4ca83..df743e2b 100644 --- a/src/transition/transition.ts +++ b/src/transition/transition.ts @@ -368,14 +368,13 @@ export class Transition implements IHookRegistry { } /** - * If the current transition is a redirect, returns the transition that was redirected. - * * Gets the transition from which this transition was redirected. * + * If the current transition is a redirect, this method returns the transition that was redirected. * * #### Example: * ```js - * let transitionA = $state.go('A').transitionA + * let transitionA = $state.go('A').transition * transitionA.onStart({}, () => $state.target('B')); * $transitions.onSuccess({ to: 'B' }, (trans) => { * trans.to().name === 'B'; // true @@ -389,6 +388,37 @@ export class Transition implements IHookRegistry { return this._options.redirectedFrom || null; } + /** + * Gets the original transition in a redirect chain + * + * A transition might belong to a long chain of multiple redirects. + * This method walks the [[redirectedFrom]] chain back to the original (first) transition in the chain. + * + * #### Example: + * ```js + * // states + * registry.register({ name: 'A', redirectTo: 'B' }); + * registry.register({ name: 'B', redirectTo: 'C' }); + * registry.register({ name: 'C', redirectTo: 'D' }); + * registry.register({ name: 'D' }); + * + * let transitionA = $state.go('A').transition + * + * $transitions.onSuccess({ to: 'D' }, (trans) => { + * trans.to().name === 'D'; // true + * trans.redirectedFrom().to().name === 'C'; // true + * trans.originalTransition() === transitionA; // true + * trans.originalTransition().to().name === 'A'; // true + * }); + * ``` + * + * @returns The original Transition that started a redirect chain + */ + originalTransition(): Transition { + let rf = this.redirectedFrom(); + return (rf && rf.originalTransition()) || this; + } + /** * Get the transition options *