Skip to content

Commit ca45957

Browse files
BC-BREAK: Transition Hooks are no longer injected (onBefore/onStart/onExit/onRetain/onEnter/onFinish/onSuccess/onError)
Previously, a hook like `['$state', ($state) => $state.target('foo')]` would get `$state` injected. Now, all hooks receive three parameters: - transition: the current Transition - injector: the $injector (ng1) or Injector (ng2) or fake injector (non-angular) - state: for onEnter/onRetain/onExit hooks only, the State which the hook is being run for. This value will be null for onBefore/onStart/onFinish/onSuccess/onError hooks. Refactor your hooks from: `['$state', ($state) => $state.target('foo')]` to: `(trans, injector) => injector.get('$state').target('foo')` feat(onEnter): Hooks receive 3 args: (Transition, Injector, State) and are not injectable feat(onEnter): state declaration onEnter hooks are still injected
1 parent 3f78850 commit ca45957

28 files changed

+588
-458
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
"test:ng1": "karma start config/karma.ng15.js",
1313
"test:ng1:debug": "karma start config/karma.ng15.js --singleRun=false --browsers=Chrome --autoWatch=true --autoWatchInterval=1",
14+
"test:ng1:watch": "node_modules/watch/cli.js 'npm run test:ng1' src test",
1415

1516
"test:ng12": "karma start config/karma.ng12.js",
1617
"test:ng13": "karma start config/karma.ng13.js",

src/common/strings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function fnToString(fn: IInjectable) {
6868
const isTransitionRejectionPromise = Rejection.isTransitionRejectionPromise;
6969

7070
let stringifyPatternFn = null;
71-
let stringifyPattern = function(val) {
71+
let stringifyPattern = function(value) {
7272
stringifyPatternFn = stringifyPatternFn || pattern([
7373
[not(isDefined), val("undefined")],
7474
[isNull, val("null")],
@@ -81,7 +81,7 @@ let stringifyPattern = function(val) {
8181
[val(true), identity]
8282
]);
8383

84-
return stringifyPatternFn(val);
84+
return stringifyPatternFn(value);
8585
};
8686

8787
export function stringify(o: Object) {

src/globals.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class UIRouterGlobals {
5050
successfulTransitions = new Queue<Transition>([], 1);
5151

5252
constructor(transitionService: TransitionService) {
53-
const beforeNewTransition = ($transition$) => {
53+
const beforeNewTransition = ($transition$: Transition) => {
5454

5555
this.transition = $transition$;
5656
this.transitionHistory.enqueue($transition$);
@@ -70,6 +70,6 @@ export class UIRouterGlobals {
7070

7171
};
7272

73-
transitionService.onBefore({}, ['$transition$', beforeNewTransition]);
73+
transitionService.onBefore({}, beforeNewTransition);
7474
}
7575
}

src/ng1.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
export * from "./core";
88

99
export * from "./ng1/services";
10-
export * from "./ng1/viewsBuilder";
11-
export * from "./ng1/resolvesBuilder";
10+
export * from "./ng1/statebuilders/views";
11+
export * from "./ng1/statebuilders/resolve";
1212

1313
import "./ng1/stateDirectives";
1414
import "./ng1/stateFilters";

src/ng1/services.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ import {Resolvable} from "../resolve/resolvable";
2020
import {ResolveContext} from "../resolve/resolveContext";
2121
import {State} from "../state/stateObject";
2222
import {trace} from "../common/trace";
23-
import {ng1ViewsBuilder, ng1ViewConfigFactory, Ng1ViewConfig} from "./viewsBuilder";
23+
import {ng1ViewsBuilder, ng1ViewConfigFactory, Ng1ViewConfig} from "./statebuilders/views";
2424
import {TemplateFactory} from "./templateFactory";
25-
import {ng1ResolveBuilder} from "./resolvesBuilder";
25+
import {ng1ResolveBuilder} from "./statebuilders/resolve";
2626
import {StateParams} from "../params/stateParams";
2727
import {TransitionService} from "../transition/transitionService";
2828
import {StateService} from "../state/stateService";
2929
import {StateProvider} from "../state/state";
3030
import {UrlRouterProvider, UrlRouter} from "../url/urlRouter";
3131
import {UrlMatcherFactory} from "../url/urlMatcherFactory";
32+
import {Transition} from "../transition/transition";
33+
import {getStateHookBuilder} from "./statebuilders/onEnterExitRetain";
3234

3335
/** @hidden */
3436
let app = angular.module("ui.router.angular1", []);
@@ -166,9 +168,12 @@ function ng1UIRouter($locationProvider) {
166168
// Create a new instance of the Router when the ng1UIRouterProvider is initialized
167169
router = new UIRouter();
168170

169-
// Apply ng1 `views` builder to the StateBuilder
171+
// Apply ng1 specific StateBuilder code for `views`, `resolve`, and `onExit/Retain/Enter` properties
170172
router.stateRegistry.decorator("views", ng1ViewsBuilder);
171173
router.stateRegistry.decorator("resolve", ng1ResolveBuilder);
174+
router.stateRegistry.decorator("onExit", getStateHookBuilder("onExit"));
175+
router.stateRegistry.decorator("onRetain", getStateHookBuilder("onRetain"));
176+
router.stateRegistry.decorator("onEnter", getStateHookBuilder("onEnter"));
172177

173178
router.viewService.viewConfigFactory('ng1', ng1ViewConfigFactory);
174179

@@ -279,8 +284,8 @@ angular.module('ui.router.state').factory('$stateParams', ['ng1UIRouter', (ng1UI
279284

280285
// $transitions service and $transitionsProvider
281286
function getTransitionsProvider() {
282-
loadAllControllerLocals.$inject = ['$transition$'];
283-
function loadAllControllerLocals($transition$) {
287+
// TODO: check if we can remove loadAllControllerLocals. Shouldn't be necessary without JIT resolve policy
288+
function loadAllControllerLocals($transition$: Transition) {
284289
const loadLocals = (vc: Ng1ViewConfig) => {
285290
let node = (<Node> find($transition$.treeChanges().to, propEq('state', vc.viewDecl.$context)));
286291
// Temporary fix; This whole callback should be nuked when fixing #2662
@@ -297,7 +302,7 @@ function getTransitionsProvider() {
297302
.then(() => vc.locals = map(resolvables, res => res.data));
298303
};
299304

300-
let loadAllLocals = $transition$.views("entering").filter(vc => !!vc.controller).map(loadLocals);
305+
let loadAllLocals = $transition$.views("entering").filter(vc => !!(<Ng1ViewConfig>vc).controller).map(loadLocals);
301306
return services.$q.all(loadAllLocals).then(noop);
302307
}
303308
router.transitionService.onFinish({}, loadAllControllerLocals);

src/ng1/stateDirectives.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,7 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate, $transitio
334334
};
335335

336336
$scope.$on('$stateChangeSuccess', update);
337-
let updateAfterTransition = ['$transition$', function($transition$) { $transition$.promise.then(update); }];
338-
let deregisterFn = $transitions.onStart({}, updateAfterTransition);
339-
$scope.$on('$destroy', deregisterFn);
337+
$scope.$on('$destroy', $transitions.onStart({}, (trans) => trans.promise.then(update) && null));
340338

341339
function addState(stateName, stateParams, activeClass) {
342340
var state = $state.get(stateName, stateContext($element));

src/ng1/stateEvents.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,15 @@ var $stateNotFound;
153153
return memo;
154154
}
155155

156-
stateChangeStartHandler.$inject = ['$transition$', '$stateEvents', '$rootScope', '$state', '$urlRouter'];
157-
function stateChangeStartHandler($transition$: Transition, $stateEvents, $rootScope, $state, $urlRouter) {
156+
function stateChangeStartHandler($transition$: Transition, $injector) {
158157
if (!$transition$.options().notify || !$transition$.valid() || $transition$.ignored())
159158
return;
160159

160+
let $stateEvents = $injector.get('$stateEvents');
161+
let $rootScope = $injector.get('$rootScope');
162+
let $state = $injector.get('$state');
163+
let $urlRouter = $injector.get('$urlRouter');
164+
161165
let enabledEvents = $stateEvents.provider.enabled();
162166

163167

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/** @module ng1 */ /** */
2+
import {State} from "../../state/stateObject";
3+
import {TransitionStateHookFn, HookResult} from "../../transition/interface";
4+
import {Transition} from "../../transition/transition";
5+
import IInjectorService = angular.auto.IInjectorService;
6+
import {services} from "../../common/coreservices";
7+
8+
/**
9+
* This is a [[StateBuilder.builder]] function for angular1 `onEnter`, `onExit`,
10+
* `onRetain` callback hooks on a [[Ng1StateDeclaration]].
11+
*
12+
* When the [[StateBuilder]] builds a [[State]] object from a raw [[StateDeclaration]], this builder
13+
* ensures that those hooks are injectable for angular-ui-router (ng1).
14+
*/
15+
export const getStateHookBuilder = (hookName) =>
16+
function stateHookBuilder(state: State, parentFn): TransitionStateHookFn {
17+
let hook = state[hookName];
18+
if (!hook) return;
19+
20+
return function decoratedNg1Hook(trans: Transition, inj: IInjectorService): HookResult {
21+
services.$injector.invoke(hook, this, trans.resolves());
22+
}
23+
};

src/ng1/resolvesBuilder.ts renamed to src/ng1/statebuilders/resolve.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @module ng1 */ /** */
2-
import {State} from "../state/stateObject";
3-
import {forEach} from "../common/common";
4-
import {isString} from "../common/predicates";
2+
import {State} from "../../state/stateObject";
3+
import {forEach} from "../../common/common";
4+
import {isString} from "../../common/predicates";
55

66
/**
77
* This is a [[StateBuilder.builder]] function for angular1 `resolve:` block on a [[Ng1StateDeclaration]].

src/ng1/viewsBuilder.ts renamed to src/ng1/statebuilders/views.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
/** @module ng1 */ /** */
2-
import {State} from "../state/stateObject";
3-
import {pick, forEach, anyTrueR, unnestR} from "../common/common";
4-
import {kebobString} from "../common/strings";
5-
import {ViewConfig} from "../view/interface";
6-
import {Ng1ViewDeclaration} from "./interface";
7-
import {ViewService} from "../view/view";
8-
import {isInjectable, isDefined, isString, isObject} from "../common/predicates";
9-
import {services} from "../common/coreservices";
10-
import {trace} from "../common/trace";
11-
import {Node} from "../path/node";
12-
import {TemplateFactory} from "./templateFactory";
13-
import {ResolveContext} from "../resolve/resolveContext";
2+
import {State} from "../../state/stateObject";
3+
import {pick, forEach, anyTrueR, unnestR} from "../../common/common";
4+
import {kebobString} from "../../common/strings";
5+
import {ViewConfig} from "../../view/interface";
6+
import {Ng1ViewDeclaration} from "../interface";
7+
import {ViewService} from "../../view/view";
8+
import {isInjectable, isDefined, isString, isObject} from "../../common/predicates";
9+
import {services} from "../../common/coreservices";
10+
import {trace} from "../../common/trace";
11+
import {Node} from "../../path/node";
12+
import {TemplateFactory} from "../templateFactory";
13+
import {ResolveContext} from "../../resolve/resolveContext";
1414

1515
export const ng1ViewConfigFactory = (node, view) => new Ng1ViewConfig(node, view);
1616

0 commit comments

Comments
 (0)