Skip to content

Commit 6ae7820

Browse files
committed
Implementing $state.go(), for relative transitions & param inheritance.
1 parent 5eac2fe commit 6ae7820

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

src/common.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,49 @@ function merge(dst) {
3535
return dst;
3636
}
3737

38+
/**
39+
* Finds the common ancestor path between two states.
40+
*
41+
* @param {Object} first The first state.
42+
* @param {Object} second The second state.
43+
* @return {Array} Returns an array of state names in descending order, not including the root.
44+
*/
45+
function ancestors(first, second) {
46+
var path = [];
47+
48+
for (var n in first.path) {
49+
if (first.path[n] === "") continue;
50+
if (!second.path[n]) break;
51+
path.push(first.path[n]);
52+
}
53+
return path;
54+
}
55+
56+
/**
57+
* Merges a set of parameters with all parameters inherited between the common parents of the
58+
* current state and a given destination state.
59+
*
60+
* @param {Object} currentParams The value of the current state parameters ($stateParams).
61+
* @param {Object} newParams The set of parameters which will be composited with inherited params.
62+
* @param {Object} $current Internal definition of object representing the current state.
63+
* @param {Object} $to Internal definition of object representing state to transition to.
64+
*/
65+
function inheritParams(currentParams, newParams, $current, $to) {
66+
var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
67+
68+
for (var i in parents) {
69+
if (!parents[i].params || !parents[i].params.length) continue;
70+
parentParams = parents[i].params;
71+
72+
for (var j in parentParams) {
73+
if (inheritList.indexOf(parentParams[j]) >= 0) continue;
74+
inheritList.push(parentParams[j]);
75+
inherited[parentParams[j]] = currentParams[parentParams[j]];
76+
}
77+
}
78+
return extend({}, inherited, newParams);
79+
}
80+
3881
angular.module('ui.util', ['ng']);
3982
angular.module('ui.router', ['ui.util']);
4083
angular.module('ui.state', ['ui.router', 'ui.util']);

src/state.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,11 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
199199
transition: null
200200
};
201201

202-
// $state.go = function go(to, params) {
203-
// };
202+
$state.go = function go(to, params, options) {
203+
var toState = findState(to, $state.$current);
204+
params = inheritParams($stateParams, params || {}, $state.$current, toState);
205+
return this.transitionTo(toState, params, options);
206+
};
204207

205208
$state.transitionTo = function transitionTo(to, toParams, updateLocation) {
206209
if (!isDefined(updateLocation)) updateLocation = true;

test/stateSpec.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,30 @@ describe('state', function () {
210210
}));
211211
});
212212

213+
describe('.go()', function() {
214+
it('transitions to a relative state', inject(function ($state, $q) {
215+
$state.transitionTo('about.person.item', { id: 5 });
216+
$q.flush();
217+
$state.go('^.^.sidebar');
218+
$q.flush();
219+
expect($state.$current.name).toBe('about.sidebar');
220+
}));
221+
222+
it('keeps parameters from common ancestor states', inject(function ($state, $stateParams, $q) {
223+
$state.transitionTo('about.person', { person: 'bob' });
224+
$q.flush();
225+
226+
$state.go('^item', { id: 5 });
227+
$q.flush();
228+
229+
expect($state.$current.name).toBe('about.person.item');
230+
expect($stateParams).toEqual({ person: 'bob', id: '5' });
231+
232+
$state.go('^.^.sidebar');
233+
$q.flush();
234+
expect($state.$current.name).toBe('about.sidebar');
235+
}));
236+
});
213237

214238
describe('.current', function () {
215239
it('is always defined', inject(function ($state) {
@@ -345,7 +369,7 @@ describe('state', function () {
345369
}));
346370
});
347371

348-
describe('default properties', function () {
372+
describe('default properties', function() {
349373
it('should always have a name', inject(function ($state, $q) {
350374
$state.transitionTo(A);
351375
$q.flush();
@@ -403,5 +427,11 @@ describe('state', function () {
403427
it('should always have a resolve object', inject(function ($state) {
404428
expect($state.$current.resolve).toEqual({});
405429
}));
430+
431+
it('should include itself and parent states', inject(function ($state, $q) {
432+
$state.transitionTo(DD);
433+
$q.flush();
434+
expect($state.$current.includes).toEqual({ '': true, D: true, DD: true });
435+
}));
406436
});
407437
});

0 commit comments

Comments
 (0)