Skip to content

Commit 0c123c3

Browse files
fix(Transition): Do not reuse resolves for reloaded state during redirect
closes #2539
1 parent 081da32 commit 0c123c3

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

src/state/stateObject.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class State {
3232
public navigable: State;
3333
public path: State[];
3434
public data: any;
35-
public includes: (name: string) => boolean;
35+
public includes: { [name: string] : boolean };
3636

3737
constructor(config?: StateDeclaration) {
3838
extend(this, config);

src/transition/transition.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,16 @@ export class Transition implements IHookRegistry {
295295
targetState = new TargetState(targetState.identifier(), targetState.$state(), targetState.params(), newOptions);
296296

297297
let redirectTo = new Transition(this._treeChanges.from, targetState, this._transitionService);
298+
let reloadState = targetState.options().reloadState;
298299

299300
// If the current transition has already resolved any resolvables which are also in the redirected "to path", then
300301
// add those resolvables to the redirected transition. Allows you to define a resolve at a parent level, wait for
301302
// the resolve, then redirect to a child state based on the result, and not have to re-fetch the resolve.
302303
let redirectedPath = this.treeChanges().to;
303-
let matching: Node[] = Node.matching(redirectTo.treeChanges().to, redirectedPath);
304+
let copyResolvesFor: Node[] = Node.matching(redirectTo.treeChanges().to, redirectedPath)
305+
.filter(node => !reloadState || !reloadState.includes[node.state.name]);
304306
const includeResolve = (resolve, key) => ['$stateParams', '$transition$'].indexOf(key) === -1;
305-
matching.forEach((node, idx) => extend(node.resolves, filter(redirectedPath[idx].resolves, includeResolve)));
307+
copyResolvesFor.forEach((node, idx) => extend(node.resolves, filter(redirectedPath[idx].resolves, includeResolve)));
306308

307309
return redirectTo;
308310
}

test/stateSpec.js

+39-8
Original file line numberDiff line numberDiff line change
@@ -2095,14 +2095,21 @@ describe('otherwise and state redirects', function() {
20952095
});
20962096

20972097

2098-
describe('hook redirects from .otherwise()', function() {
2099-
var log;
2098+
describe('hook redirects', function() {
2099+
var log, resolvelog;
21002100
beforeEach(module(function ($stateProvider, $urlRouterProvider) {
2101-
log = "";
2101+
log = resolvelog = "";
21022102
$urlRouterProvider.otherwise('/home');
2103-
$stateProvider
2104-
.state('home', { url: '/home', template: 'home', controller: function() { log += "homeCtrl;"; } })
2105-
.state('loginPage', { url: '/login', template: 'login' });
2103+
$stateProvider.state('home', {
2104+
url: '/home',
2105+
template: 'home <ui-view></ui-view>',
2106+
controller: function () { log += "homeCtrl;"; },
2107+
resolve: {
2108+
foo: function () { resolvelog += "fooResolve;"; return "foo"; }
2109+
}
2110+
})
2111+
.state('home.foo', {url: '/foo', template: 'foo'})
2112+
.state('loginPage', {url: '/login', template: 'login'});
21062113
}));
21072114

21082115
beforeEach(inject(function($compile, $rootScope) {
@@ -2111,7 +2118,7 @@ describe('hook redirects from .otherwise()', function() {
21112118
}));
21122119

21132120
// Test for #2455
2114-
it("should go to the redirect-to target state and url", inject(function($transitions, $q, $state, $location) {
2121+
it("from .otherwise() should go to the redirect-to target state and url", inject(function($transitions, $q, $state, $location) {
21152122
$transitions.onBefore({ to: 'home' }, function() {
21162123
return $state.target('loginPage', {}, { location: true });
21172124
});
@@ -2132,7 +2139,7 @@ describe('hook redirects from .otherwise()', function() {
21322139

21332140
$transitions.onBefore({ to: 'home' }, function($state, $transition$) {
21342141
var options = $transition$.options();
2135-
if (!options.reload && count++ < 2) {
2142+
if (!options.reload && count++ < 5) {
21362143
return $state.target($transition$.to(), $transition$.params("to"), extend({}, options, {reload: true}));
21372144
}
21382145
});
@@ -2142,4 +2149,28 @@ describe('hook redirects from .otherwise()', function() {
21422149
expect($state.current.name).toBe("home");
21432150
expect(log).toBe("homeCtrl;homeCtrl;");
21442151
}));
2152+
2153+
// Test for #2539
2154+
it("should re-resolve when reloading during a redirect", inject(function($transitions, $q, $state, $trace) {
2155+
var count = 0;
2156+
$q.flush();
2157+
2158+
expect($state.current.name).toBe("home");
2159+
expect(resolvelog).toBe("fooResolve;");
2160+
2161+
$state.go('home.foo'); $q.flush();
2162+
expect(resolvelog).toBe("fooResolve;");
2163+
2164+
$transitions.onStart({ to: 'home' }, function($transition$, $state) {
2165+
if (!$transition$.options().reload && count++ < 5) {
2166+
console.log("forcing re-enter (reload) of home state ");
2167+
var options = $transition$.options();
2168+
return $state.target($transition$.to(), $transition$.params("to"), extend({}, options, {reload: true}));
2169+
}
2170+
});
2171+
2172+
$state.go('home'); $q.flush();
2173+
expect($state.current.name).toBe("home");
2174+
expect(resolvelog).toBe("fooResolve;fooResolve;");
2175+
}));
21452176
});

0 commit comments

Comments
 (0)