Skip to content

Commit a06948b

Browse files
fix(resolve): Allow resolve's state context to be injected as $state$
refactor(hooks): Move a) core resolvables and b) update globals to transition hooks. Closes angular-ui/ui-router#3273
1 parent f7f353e commit a06948b

File tree

7 files changed

+90
-61
lines changed

7 files changed

+90
-61
lines changed

karma.conf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module.exports = function (karma) {
4343

4444
module: {
4545
loaders: [
46-
{ test: /\.ts$/, loader: "awesome-typescript-loader?declaration=false&configFileName=test/tsconfig.json" }
46+
{ test: /\.ts$/, loader: "awesome-typescript-loader?noEmit=true&configFileName=test/tsconfig.json" }
4747
]
4848
},
4949

src/globals.ts

-26
Original file line numberDiff line numberDiff line change
@@ -63,30 +63,4 @@ export class Globals implements UIRouterGlobals {
6363

6464
/** @internalapi */
6565
successfulTransitions = new Queue<Transition>([], 1);
66-
67-
/** @hidden */
68-
constructor(transitionService: TransitionService) {
69-
// TODO: This probably belongs in a hooks/globals.ts
70-
const beforeNewTransition = ($transition$: Transition) => {
71-
72-
this.transition = $transition$;
73-
this.transitionHistory.enqueue($transition$);
74-
75-
const updateGlobalState = () => {
76-
this.successfulTransitions.enqueue($transition$);
77-
this.$current = $transition$.$to();
78-
this.current = this.$current.self;
79-
copy($transition$.params(), this.params);
80-
};
81-
82-
$transition$.onSuccess({}, updateGlobalState, {priority: 10000});
83-
84-
const clearCurrentTransition = () => { if (this.transition === $transition$) this.transition = null; };
85-
86-
$transition$.promise.then(clearCurrentTransition, clearCurrentTransition);
87-
88-
};
89-
90-
transitionService.onBefore({}, beforeNewTransition);
91-
}
9266
}

src/hooks/coreResolvables.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/** @module hooks */ /** */
2+
import { Transition } from "../transition/transition";
3+
import { UIRouter } from "../router";
4+
import { TransitionService } from "../transition/transitionService";
5+
6+
function addCoreResolvables(trans: Transition) {
7+
trans.addResolvable({ token: UIRouter, deps: [], resolveFn: () => trans.router, data: trans.router }, "");
8+
trans.addResolvable({ token: Transition, deps: [], resolveFn: () => trans, data: trans }, "");
9+
trans.addResolvable({ token: '$transition$', deps: [], resolveFn: () => trans, data: trans }, "");
10+
trans.addResolvable({ token: '$stateParams', deps: [], resolveFn: () => trans.params(), data: trans.params() }, "");
11+
12+
trans.entering().forEach(state => {
13+
trans.addResolvable({ token: '$state$', deps: [], resolveFn: () => state, data: state }, state);
14+
});
15+
}
16+
17+
export const registerAddCoreResolvables= (transitionService: TransitionService) =>
18+
transitionService.onCreate({}, addCoreResolvables);

src/hooks/updateGlobals.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/** @module hooks */ /** for typedoc */
2+
import { Transition } from "../transition/transition";
3+
import { copy } from "../common/common";
4+
import { Globals } from "../globals";
5+
import { TransitionService } from "../transition/transitionService";
6+
7+
/**
8+
* A [[TransitionHookFn]] which updates global UI-Router state
9+
*
10+
* Registered using `transitionService.onBefore({}, updateGlobalState);`
11+
*
12+
* Before a [[Transition]] starts, updates the global value of "the current transition" ([[Globals.transition]]).
13+
* After a successful [[Transition]], updates the global values of "the current state"
14+
* ([[Globals.current]] and [[Globals.$current]]) and "the current param values" ([[Globals.params]]).
15+
*
16+
* See also the deprecated properties:
17+
* [[StateService.transition]], [[StateService.current]], [[StateService.params]]
18+
*/
19+
const updateGlobalState = (trans: Transition) => {
20+
let globals = trans.router.globals as Globals;
21+
globals.transition = trans;
22+
globals.transitionHistory.enqueue(trans);
23+
24+
const updateGlobalState = () => {
25+
globals.successfulTransitions.enqueue(trans);
26+
globals.$current = trans.$to();
27+
globals.current = globals.$current.self;
28+
copy(trans.params(), globals.params);
29+
};
30+
31+
trans.onSuccess({}, updateGlobalState, {priority: 10000});
32+
33+
const clearCurrentTransition = () => {
34+
// Do not clear globals.transition if a different transition has started in the meantime
35+
if (globals.transition === trans) globals.transition = null;
36+
};
37+
38+
trans.promise.then(clearCurrentTransition, clearCurrentTransition);
39+
};
40+
41+
export const registerUpdateGlobalState = (transitionService: TransitionService) =>
42+
transitionService.onBefore({}, updateGlobalState);

src/router.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class UIRouter {
4848
transitionService: TransitionService = new TransitionService(this);
4949

5050
/** Global router state */
51-
globals: UIRouterGlobals = new Globals(this.transitionService);
51+
globals: UIRouterGlobals = new Globals();
5252

5353
/**
5454
* Deprecated for public use. Use [[urlService]] instead.

src/transition/transition.ts

-14
Original file line numberDiff line numberDiff line change
@@ -161,27 +161,13 @@ export class Transition implements IHookRegistry {
161161
TransitionHook.runAllHooks(onCreateHooks);
162162

163163
this.applyViewConfigs(router);
164-
this.applyRootResolvables(router);
165164
}
166165

167166
private applyViewConfigs(router: UIRouter) {
168167
let enteringStates = this._treeChanges.entering.map(node => node.state);
169168
PathFactory.applyViewConfigs(router.transitionService.$view, this._treeChanges.to, enteringStates);
170169
}
171170

172-
private applyRootResolvables(router: UIRouter) {
173-
let rootResolvables: Resolvable[] = [
174-
new Resolvable(UIRouter, () => router, [], undefined, router),
175-
new Resolvable(Transition, () => this, [], undefined, this),
176-
new Resolvable('$transition$', () => this, [], undefined, this),
177-
new Resolvable('$stateParams', () => this.params(), [], undefined, this.params())
178-
];
179-
180-
let rootNode: PathNode = this._treeChanges.to[0];
181-
let context = new ResolveContext(this._treeChanges.to);
182-
context.addResolvables(rootResolvables, rootNode.state);
183-
}
184-
185171
/**
186172
* @internalapi
187173
*

src/transition/transitionService.ts

+28-19
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
/**
22
* @coreapi
33
* @module transition
4-
*/ /** for typedoc */
4+
*/
5+
/** for typedoc */
56
import {
6-
IHookRegistry, TransitionOptions, TransitionHookScope, TransitionHookPhase, TransitionCreateHookFn,
7-
HookMatchCriteria, HookRegOptions, PathTypes, PathType, RegisteredHooks, IHookRegistration, TransitionHookFn,
8-
TransitionStateHookFn
7+
IHookRegistry, TransitionOptions, TransitionHookScope, TransitionHookPhase, TransitionCreateHookFn, HookMatchCriteria,
8+
HookRegOptions, PathTypes, PathType, RegisteredHooks, TransitionHookFn, TransitionStateHookFn
99
} from "./interface";
1010
import { Transition } from "./transition";
1111
import { makeEvent, RegisteredHook } from "./hookRegistry";
1212
import { TargetState } from "../state/targetState";
1313
import { PathNode } from "../path/node";
1414
import { ViewService } from "../view/view";
1515
import { UIRouter } from "../router";
16+
import { registerAddCoreResolvables } from "../hooks/coreResolvables";
17+
import { registerRedirectToHook } from "../hooks/redirectTo";
18+
import { registerOnExitHook, registerOnRetainHook, registerOnEnterHook } from "../hooks/onEnterExitRetain";
1619
import { registerEagerResolvePath, registerLazyResolveState } from "../hooks/resolve";
1720
import { registerLoadEnteringViews, registerActivateViews } from "../hooks/views";
21+
import { registerUpdateGlobalState } from "../hooks/updateGlobals";
1822
import { registerUpdateUrl } from "../hooks/url";
19-
import { registerRedirectToHook } from "../hooks/redirectTo";
20-
import { registerOnExitHook, registerOnRetainHook, registerOnEnterHook } from "../hooks/onEnterExitRetain";
2123
import { registerLazyLoadHook } from "../hooks/lazyLoad";
2224
import { TransitionEventType } from "./transitionEventType";
2325
import { TransitionHook, GetResultHandler, GetErrorHandler } from "./transitionHook";
@@ -167,6 +169,7 @@ export class TransitionService implements IHookRegistry, Disposable {
167169
* @hidden
168170
*/
169171
_deregisterHookFns: {
172+
addCoreResolves: Function;
170173
redirectTo: Function;
171174
onExit: Function;
172175
onRetain: Function;
@@ -175,6 +178,7 @@ export class TransitionService implements IHookRegistry, Disposable {
175178
lazyResolve: Function;
176179
loadViews: Function;
177180
activateViews: Function;
181+
updateGlobals: Function;
178182
updateUrl: Function;
179183
lazyLoad: Function;
180184
};
@@ -195,7 +199,7 @@ export class TransitionService implements IHookRegistry, Disposable {
195199
this._defineDefaultPaths();
196200
this._defineDefaultEvents();
197201

198-
this._registerDefaultTransitionHooks();
202+
this._registerCoreTransitionHooks();
199203
}
200204

201205
/**
@@ -312,29 +316,34 @@ export class TransitionService implements IHookRegistry, Disposable {
312316
}
313317

314318
/** @hidden */
315-
private _registerDefaultTransitionHooks() {
319+
private _registerCoreTransitionHooks() {
316320
let fns = this._deregisterHookFns;
317321

322+
fns.addCoreResolves = registerAddCoreResolvables(this);
323+
318324
// Wire up redirectTo hook
319-
fns.redirectTo = registerRedirectToHook(this);
325+
fns.redirectTo = registerRedirectToHook(this);
320326

321327
// Wire up onExit/Retain/Enter state hooks
322-
fns.onExit = registerOnExitHook(this);
323-
fns.onRetain = registerOnRetainHook(this);
324-
fns.onEnter = registerOnEnterHook(this);
328+
fns.onExit = registerOnExitHook(this);
329+
fns.onRetain = registerOnRetainHook(this);
330+
fns.onEnter = registerOnEnterHook(this);
325331

326332
// Wire up Resolve hooks
327-
fns.eagerResolve = registerEagerResolvePath(this);
328-
fns.lazyResolve = registerLazyResolveState(this);
329-
333+
fns.eagerResolve = registerEagerResolvePath(this);
334+
fns.lazyResolve = registerLazyResolveState(this);
335+
330336
// Wire up the View management hooks
331-
fns.loadViews = registerLoadEnteringViews(this);
332-
fns.activateViews = registerActivateViews(this);
337+
fns.loadViews = registerLoadEnteringViews(this);
338+
fns.activateViews = registerActivateViews(this);
339+
340+
// Updates global state after a transition
341+
fns.updateGlobals = registerUpdateGlobalState(this);
333342

334343
// After globals.current is updated at priority: 10000
335-
fns.updateUrl = registerUpdateUrl(this);
344+
fns.updateUrl = registerUpdateUrl(this);
336345

337346
// Lazy load state trees
338-
fns.lazyLoad = registerLazyLoadHook(this);
347+
fns.lazyLoad = registerLazyLoadHook(this);
339348
}
340349
}

0 commit comments

Comments
 (0)