diff --git a/src/ng1/statebuilders/onEnterExitRetain.ts b/src/ng1/statebuilders/onEnterExitRetain.ts index 316f751cb..b20e0e5c3 100644 --- a/src/ng1/statebuilders/onEnterExitRetain.ts +++ b/src/ng1/statebuilders/onEnterExitRetain.ts @@ -14,9 +14,12 @@ import { getLocals } from "../services"; export const getStateHookBuilder = (hookName: "onEnter"|"onExit"|"onRetain") => function stateHookBuilder(state: State, parentFn: BuilderFunction): TransitionStateHookFn { let hook = state[hookName]; + let pathname = hookName === 'onExit' ? 'from' : 'to'; + function decoratedNg1Hook(trans: Transition, state: State): HookResult { - let resolveContext = new ResolveContext(trans.treeChanges().to); - return services.$injector.invoke(hook, this, extend({ $state$: state }, getLocals(resolveContext))); + let resolveContext = new ResolveContext(trans.treeChanges(pathname)); + var locals = extend(getLocals(resolveContext), { $state$: state, $transition$: trans }); + return services.$injector.invoke(hook, this, locals); } return hook ? decoratedNg1Hook : undefined; diff --git a/test/stateSpec.js b/test/stateSpec.js index ccf4a5c87..2e158f750 100644 --- a/test/stateSpec.js +++ b/test/stateSpec.js @@ -11,12 +11,13 @@ var html5Compat = require('./util/testUtilsNg1').html5Compat; describe('state', function () { - var $injector, $stateProvider, locationProvider, templateParams, template, ctrlName, errors; + var $uiRouter, $injector, $stateProvider, locationProvider, templateParams, template, ctrlName, errors; - beforeEach(module('ui.router', function($locationProvider) { + beforeEach(module('ui.router', function($locationProvider, $uiRouterProvider) { errors = []; locationProvider = $locationProvider; $locationProvider.html5Mode(false); + $uiRouter = $uiRouterProvider.router; })); var log, logEvents, logEnterExit; @@ -635,6 +636,32 @@ describe('state', function () { 'A.onEnter;'); })); + // test for #3081 + it('injects resolve values from the exited state into onExit', (function(done) { + const registry = $uiRouter.stateRegistry; + registry.register({ + name: 'design', + url: '/design', + resolve: { cc: function() { return 'cc resolve'; } }, + onExit: function(cc, $state$, $transition$) { + expect($transition$.to().name).toBe('A'); + expect($transition$.from().name).toBe('design'); + + expect($state$.self).toBe(registry.get('design')); + + expect(cc).toBe('cc resolve'); + + done(); + } + }); + + $state.go("design"); + $q.flush(); + + $state.go("A"); + $q.flush(); + })); + it('doesn\'t transition to parent state when child has no URL', inject(function ($state, $q) { $state.transitionTo('about.sidebar'); $q.flush(); expect($state.current.name).toEqual('about.sidebar');