Skip to content

Commit 52f1308

Browse files
feat(Transition): expose the current UiRouter object as a public property
feat(UiInjector): add `getAsync` method refactor(UiInjector): rename UIRInjector to UiInjector
1 parent 38432f4 commit 52f1308

File tree

9 files changed

+87
-24
lines changed

9 files changed

+87
-24
lines changed

src/common/interface.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* An interface for getting values from dependency injection.
33
*/
4-
export interface UIRInjector {
4+
export interface UiInjector {
55
/**
66
* Gets a value from the injector
77
*
@@ -28,4 +28,23 @@ export interface UIRInjector {
2828
* @return the Dependency Injection value that matches the key
2929
*/
3030
get(key: any): any;
31+
32+
/**
33+
* Asynchronously gets a value from the injector
34+
*
35+
* Returns a promise for a value from the injector.
36+
* Returns resolve values and/or values from the native injector (ng1/ng2).
37+
*
38+
* @example
39+
* ```js
40+
*
41+
* return injector.getAsync('myResolve').then(value => {
42+
* if (value === 'declined') return false;
43+
* });
44+
* ```
45+
*
46+
* @param key the key for the value to get. May be a string or arbitrary object.
47+
* @return a Promise for the Dependency Injection value that matches the key
48+
*/
49+
getAsync(key: any): any;
3150
}

src/hooks/onEnterExitRetain.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/** @module state */ /** for typedoc */
22
import {TransitionStateHookFn} from "../transition/interface";
3-
import {UIRInjector} from "../common/interface";
3+
import {UiInjector} from "../common/interface";
44
import {State} from "../state/stateObject";
55
import {Transition} from "../transition/transition";
66

77
export function makeEnterExitRetainHook(hookName: string): TransitionStateHookFn {
8-
return (transition: Transition, injector: UIRInjector, state: State) =>
8+
return (transition: Transition, injector: UiInjector, state: State) =>
99
state[hookName](transition, injector, state);
1010
}

src/hooks/redirectTo.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {isString, isFunction} from "../common/predicates"
2-
import {UIRInjector} from "../common/interface";
2+
import {UiInjector} from "../common/interface";
33
import {Transition} from "../transition/transition";
44
import {UiRouter} from "../router";
55
import {services} from "../common/coreservices";
@@ -10,7 +10,7 @@ import {TargetState} from "../state/targetState";
1010
*
1111
* See [[StateDeclaration.redirectTo]]
1212
*/
13-
export const redirectToHook = (transition: Transition, $injector: UIRInjector) => {
13+
export const redirectToHook = (transition: Transition, $injector: UiInjector) => {
1414
let redirect = transition.to().redirectTo;
1515
if (!redirect) return;
1616

src/hooks/url.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {UrlRouter} from "../url/urlRouter";
22
import {StateService} from "../state/stateService";
33
import {Transition} from "../transition/transition";
4-
import {UIRInjector} from "../common/interface";
4+
import {UiInjector} from "../common/interface";
55
import {UiRouter} from "../router";
66

7-
export function updateUrl(transition: Transition, injector: UIRInjector) {
7+
export function updateUrl(transition: Transition, injector: UiInjector) {
88
let options = transition.options();
99
var router: UiRouter = injector.get(UiRouter);
1010
let $state: StateService = router.stateService;

src/hooks/views.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {Transition} from "../transition/transition";
55
import {ViewService} from "../view/view";
66
import {ViewConfig} from "../view/interface";
77
import {TransitionService} from "../transition/transitionService";
8-
import {UIRInjector} from "../common/interface";
8+
import {UiInjector} from "../common/interface";
99
import {UiRouter} from "../router";
1010

1111

@@ -16,7 +16,7 @@ export function loadEnteringViews(transition) {
1616
return services.$q.all(enteringViews.map(view => view.load())).then(noop);
1717
}
1818

19-
export function activateViews(transition: Transition, injector: UIRInjector) {
19+
export function activateViews(transition: Transition, injector: UiInjector) {
2020
let enteringViews = transition.views("entering");
2121
let exitingViews = transition.views("exiting");
2222
if (!enteringViews.length && !exitingViews.length) return;

src/resolve/resolveContext.ts

+23-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {State} from "../state/stateObject";
1111
import {PathFactory} from "../path/pathFactory";
1212
import {stringify} from "../common/strings";
1313
import {Transition} from "../transition/transition";
14+
import {UiInjector} from "../common/interface";
1415

1516
var when = resolvePolicies.when;
1617
const ALL_WHENS = [when.EAGER, when.LAZY];
@@ -129,15 +130,8 @@ export class ResolveContext {
129130
return services.$q.all(promises);
130131
}
131132

132-
injector(): { get(any): any } {
133-
134-
let get = (token: any) => {
135-
var resolvable = this.getResolvable(token);
136-
if (resolvable) return resolvable.data;
137-
return services.$injector.get(token);
138-
};
139-
140-
return { get };
133+
injector(): UiInjector {
134+
return new UiInjectorImpl(this);
141135
}
142136

143137
findNode(resolvable: Resolvable): PathNode {
@@ -173,3 +167,23 @@ export class ResolveContext {
173167
return resolvable.deps.map(getDependency);
174168
}
175169
}
170+
171+
class UiInjectorImpl implements UiInjector {
172+
constructor(public context: ResolveContext) { }
173+
get(token: any) {
174+
var resolvable = this.context.getResolvable(token);
175+
if (resolvable) {
176+
if (!resolvable.resolved) {
177+
throw new Error("Resolvable async .get() not complete:" + stringify(resolvable.token))
178+
}
179+
return resolvable.data;
180+
}
181+
return services.$injector.get(token);
182+
}
183+
184+
getAsync(token: any) {
185+
var resolvable = this.context.getResolvable(token);
186+
if (resolvable) return resolvable.get(this.context);
187+
return services.$q.when(services.$injector.get(token));
188+
}
189+
}

src/state/interface.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {Transition} from "../transition/transition";
88
import {TransitionStateHookFn} from "../transition/interface";
99
import {ResolvePolicy, ResolvableLiteral} from "../resolve/interface";
1010
import {Resolvable} from "../resolve/resolvable";
11-
import {UIRInjector} from "../common/interface";
11+
import {UiInjector} from "../common/interface";
1212
import {TargetState} from "./targetState";
1313

1414
export type StateOrName = (string|StateDeclaration|State);
@@ -452,7 +452,7 @@ export interface StateDeclaration {
452452
* })
453453
*/
454454
redirectTo?: (
455-
($transition$: Transition, $injector: UIRInjector) => TargetState |
455+
($transition$: Transition, $injector: UiInjector) => TargetState |
456456
{ state: (string|StateDeclaration), params: { [key: string]: any }} |
457457
string
458458
)

src/transition/interface.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {Transition} from "./transition";
66
import {State} from "../state/stateObject";
77
import {PathNode} from "../path/node";
88
import {TargetState} from "../state/targetState";
9-
import {UIRInjector} from "../common/interface";
9+
import {UiInjector} from "../common/interface";
1010

1111
/**
1212
* The TransitionOptions object can be used to change the behavior of a transition.
@@ -183,7 +183,7 @@ export type IHookRegistration = (matchCriteria: HookMatchCriteria, callback: Hoo
183183
* - [[IHookRegistry.onError]]
184184
*/
185185
export interface TransitionHookFn {
186-
(transition: Transition, injector: UIRInjector) : HookResult
186+
(transition: Transition, injector: UiInjector) : HookResult
187187
}
188188

189189
/**
@@ -208,7 +208,7 @@ export interface TransitionHookFn {
208208
* - [[IHookRegistry.onExit]]
209209
*/
210210
export interface TransitionStateHookFn {
211-
(transition: Transition, injector: UIRInjector, state: State) : HookResult
211+
(transition: Transition, injector: UiInjector, state: State) : HookResult
212212
}
213213

214214
export type HookFn = (TransitionHookFn|TransitionStateHookFn);

src/transition/transition.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {Rejection} from "./rejectFactory";
2525
import {ResolveContext} from "../resolve/resolveContext";
2626
import {UiRouter} from "../router";
2727
import {Globals} from "../globals";
28+
import {UiInjector} from "../common/interface";
2829

2930

3031
let transitionCount = 0;
@@ -44,6 +45,14 @@ export class Transition implements IHookRegistry {
4445
$id: number;
4546
success: boolean;
4647

48+
/**
49+
* A reference to the [[UiRouter]] instance
50+
*
51+
* This reference can be used to access the router services, such as the [[StateService]]
52+
*/
53+
router: UiRouter;
54+
55+
/** @hidden */
4756
private _deferred = services.$q.defer();
4857
/**
4958
* This promise is resolved or rejected based on the outcome of the Transition.
@@ -140,7 +149,8 @@ export class Transition implements IHookRegistry {
140149
* @param targetState The target state and parameters being transitioned to (also, the transition options)
141150
* @param router The [[UiRouter]] instance
142151
*/
143-
constructor(fromPath: PathNode[], targetState: TargetState, private router: UiRouter) {
152+
constructor(fromPath: PathNode[], targetState: TargetState, router: UiRouter) {
153+
this.router = router;
144154
if (!targetState.valid()) {
145155
throw new Error(targetState.error());
146156
}
@@ -219,6 +229,26 @@ export class Transition implements IHookRegistry {
219229
return this._treeChanges[pathname].map(prop("paramValues")).reduce(mergeR, {});
220230
}
221231

232+
233+
/**
234+
* Creates a [[UiInjector]] Dependency Injector
235+
*
236+
* Returns a Dependency Injector for the Transition's target state (to state).
237+
* The injector provides resolve values which the target state has access to.
238+
*
239+
* The `UiInjector` can also provide values from the native root/global injector (ng1/ng2).
240+
*
241+
* If a `state` is provided, the injector that is returned will be limited to resolve values that the provided state has access to.
242+
*
243+
* @param state Limits the resolves provided to only the resolves the provided state has access to.
244+
* @returns a [[UiInjector]]
245+
*/
246+
injector(state?: StateOrName): UiInjector {
247+
let path: PathNode[] = this.treeChanges().to;
248+
if (state) path = PathFactory.subPath(path, node => node.state === state || node.state.name === state);
249+
return new ResolveContext(path).injector();
250+
}
251+
222252
/**
223253
* Gets all available resolve tokens (keys)
224254
*

0 commit comments

Comments
 (0)