Skip to content

Commit

Permalink
feat(Transition): expose the current UiRouter object as a public pr…
Browse files Browse the repository at this point in the history
…operty

feat(UiInjector): add `getAsync` method
refactor(UiInjector): rename UIRInjector to UiInjector
  • Loading branch information
christopherthielen committed Jun 27, 2016
1 parent 38432f4 commit 52f1308
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 24 deletions.
21 changes: 20 additions & 1 deletion src/common/interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* An interface for getting values from dependency injection.
*/
export interface UIRInjector {
export interface UiInjector {
/**
* Gets a value from the injector
*
Expand All @@ -28,4 +28,23 @@ export interface UIRInjector {
* @return the Dependency Injection value that matches the key
*/
get(key: any): any;

/**
* Asynchronously gets a value from the injector
*
* Returns a promise for a value from the injector.
* Returns resolve values and/or values from the native injector (ng1/ng2).
*
* @example
* ```js
*
* return injector.getAsync('myResolve').then(value => {
* if (value === 'declined') return false;
* });
* ```
*
* @param key the key for the value to get. May be a string or arbitrary object.
* @return a Promise for the Dependency Injection value that matches the key
*/
getAsync(key: any): any;
}
4 changes: 2 additions & 2 deletions src/hooks/onEnterExitRetain.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/** @module state */ /** for typedoc */
import {TransitionStateHookFn} from "../transition/interface";
import {UIRInjector} from "../common/interface";
import {UiInjector} from "../common/interface";
import {State} from "../state/stateObject";
import {Transition} from "../transition/transition";

export function makeEnterExitRetainHook(hookName: string): TransitionStateHookFn {
return (transition: Transition, injector: UIRInjector, state: State) =>
return (transition: Transition, injector: UiInjector, state: State) =>
state[hookName](transition, injector, state);
}
4 changes: 2 additions & 2 deletions src/hooks/redirectTo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {isString, isFunction} from "../common/predicates"
import {UIRInjector} from "../common/interface";
import {UiInjector} from "../common/interface";
import {Transition} from "../transition/transition";
import {UiRouter} from "../router";
import {services} from "../common/coreservices";
Expand All @@ -10,7 +10,7 @@ import {TargetState} from "../state/targetState";
*
* See [[StateDeclaration.redirectTo]]
*/
export const redirectToHook = (transition: Transition, $injector: UIRInjector) => {
export const redirectToHook = (transition: Transition, $injector: UiInjector) => {
let redirect = transition.to().redirectTo;
if (!redirect) return;

Expand Down
4 changes: 2 additions & 2 deletions src/hooks/url.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {UrlRouter} from "../url/urlRouter";
import {StateService} from "../state/stateService";
import {Transition} from "../transition/transition";
import {UIRInjector} from "../common/interface";
import {UiInjector} from "../common/interface";
import {UiRouter} from "../router";

export function updateUrl(transition: Transition, injector: UIRInjector) {
export function updateUrl(transition: Transition, injector: UiInjector) {
let options = transition.options();
var router: UiRouter = injector.get(UiRouter);
let $state: StateService = router.stateService;
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {Transition} from "../transition/transition";
import {ViewService} from "../view/view";
import {ViewConfig} from "../view/interface";
import {TransitionService} from "../transition/transitionService";
import {UIRInjector} from "../common/interface";
import {UiInjector} from "../common/interface";
import {UiRouter} from "../router";


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

export function activateViews(transition: Transition, injector: UIRInjector) {
export function activateViews(transition: Transition, injector: UiInjector) {
let enteringViews = transition.views("entering");
let exitingViews = transition.views("exiting");
if (!enteringViews.length && !exitingViews.length) return;
Expand Down
32 changes: 23 additions & 9 deletions src/resolve/resolveContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {State} from "../state/stateObject";
import {PathFactory} from "../path/pathFactory";
import {stringify} from "../common/strings";
import {Transition} from "../transition/transition";
import {UiInjector} from "../common/interface";

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

injector(): { get(any): any } {

let get = (token: any) => {
var resolvable = this.getResolvable(token);
if (resolvable) return resolvable.data;
return services.$injector.get(token);
};

return { get };
injector(): UiInjector {
return new UiInjectorImpl(this);
}

findNode(resolvable: Resolvable): PathNode {
Expand Down Expand Up @@ -173,3 +167,23 @@ export class ResolveContext {
return resolvable.deps.map(getDependency);
}
}

class UiInjectorImpl implements UiInjector {
constructor(public context: ResolveContext) { }
get(token: any) {
var resolvable = this.context.getResolvable(token);
if (resolvable) {
if (!resolvable.resolved) {
throw new Error("Resolvable async .get() not complete:" + stringify(resolvable.token))
}
return resolvable.data;
}
return services.$injector.get(token);
}

getAsync(token: any) {
var resolvable = this.context.getResolvable(token);
if (resolvable) return resolvable.get(this.context);
return services.$q.when(services.$injector.get(token));
}
}
4 changes: 2 additions & 2 deletions src/state/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Transition} from "../transition/transition";
import {TransitionStateHookFn} from "../transition/interface";
import {ResolvePolicy, ResolvableLiteral} from "../resolve/interface";
import {Resolvable} from "../resolve/resolvable";
import {UIRInjector} from "../common/interface";
import {UiInjector} from "../common/interface";
import {TargetState} from "./targetState";

export type StateOrName = (string|StateDeclaration|State);
Expand Down Expand Up @@ -452,7 +452,7 @@ export interface StateDeclaration {
* })
*/
redirectTo?: (
($transition$: Transition, $injector: UIRInjector) => TargetState |
($transition$: Transition, $injector: UiInjector) => TargetState |
{ state: (string|StateDeclaration), params: { [key: string]: any }} |
string
)
Expand Down
6 changes: 3 additions & 3 deletions src/transition/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {Transition} from "./transition";
import {State} from "../state/stateObject";
import {PathNode} from "../path/node";
import {TargetState} from "../state/targetState";
import {UIRInjector} from "../common/interface";
import {UiInjector} from "../common/interface";

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

/**
Expand All @@ -208,7 +208,7 @@ export interface TransitionHookFn {
* - [[IHookRegistry.onExit]]
*/
export interface TransitionStateHookFn {
(transition: Transition, injector: UIRInjector, state: State) : HookResult
(transition: Transition, injector: UiInjector, state: State) : HookResult
}

export type HookFn = (TransitionHookFn|TransitionStateHookFn);
Expand Down
32 changes: 31 additions & 1 deletion src/transition/transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {Rejection} from "./rejectFactory";
import {ResolveContext} from "../resolve/resolveContext";
import {UiRouter} from "../router";
import {Globals} from "../globals";
import {UiInjector} from "../common/interface";


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

/**
* A reference to the [[UiRouter]] instance
*
* This reference can be used to access the router services, such as the [[StateService]]
*/
router: UiRouter;

/** @hidden */
private _deferred = services.$q.defer();
/**
* This promise is resolved or rejected based on the outcome of the Transition.
Expand Down Expand Up @@ -140,7 +149,8 @@ export class Transition implements IHookRegistry {
* @param targetState The target state and parameters being transitioned to (also, the transition options)
* @param router The [[UiRouter]] instance
*/
constructor(fromPath: PathNode[], targetState: TargetState, private router: UiRouter) {
constructor(fromPath: PathNode[], targetState: TargetState, router: UiRouter) {
this.router = router;
if (!targetState.valid()) {
throw new Error(targetState.error());
}
Expand Down Expand Up @@ -219,6 +229,26 @@ export class Transition implements IHookRegistry {
return this._treeChanges[pathname].map(prop("paramValues")).reduce(mergeR, {});
}


/**
* Creates a [[UiInjector]] Dependency Injector
*
* Returns a Dependency Injector for the Transition's target state (to state).
* The injector provides resolve values which the target state has access to.
*
* The `UiInjector` can also provide values from the native root/global injector (ng1/ng2).
*
* If a `state` is provided, the injector that is returned will be limited to resolve values that the provided state has access to.
*
* @param state Limits the resolves provided to only the resolves the provided state has access to.
* @returns a [[UiInjector]]
*/
injector(state?: StateOrName): UiInjector {
let path: PathNode[] = this.treeChanges().to;
if (state) path = PathFactory.subPath(path, node => node.state === state || node.state.name === state);
return new ResolveContext(path).injector();
}

/**
* Gets all available resolve tokens (keys)
*
Expand Down

0 comments on commit 52f1308

Please sign in to comment.