Skip to content

Commit

Permalink
Fix param-only transition between child states
Browse files Browse the repository at this point in the history
Param changes only in a child-most state should not trigger a parent
transition. Previously, the whole tree was exited and re-entered if a
param owned by the child-most state is changing.
  • Loading branch information
sompylasar committed Dec 4, 2013
1 parent 6c58f06 commit f772f85
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 12 deletions.
6 changes: 4 additions & 2 deletions dist/abyssa-with-deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -2915,7 +2915,7 @@ var when = (function(global) {
/*! @license
* abyssa <https://github.com/AlexGalays/abyssa-js/>
* Author: Alexandre Galays | MIT License
* v1.2.13 (2013-11-28T09:57:47.157Z)
* v1.2.14 (2013-12-04T14:13:38.914Z)
*/
(function () {
var factory = function () {
Expand Down Expand Up @@ -3160,6 +3160,7 @@ function doTransition(enters, exits, params) {

/**
* Finds the top-most current state's parent that must be exited.
* For paramOnlyChange, fromState is also checked for owning params.
*
* @param {Abyssa.State} fromState The original state.
* @param {Abyssa.State} toState The target state.
Expand All @@ -3173,7 +3174,8 @@ function transitionRoot(fromState, toState, paramOnlyChange, paramDiff) {

// For a param-only change, the root is the top-most state owning the param(s),
if (paramOnlyChange) {
fromState.parents.slice().reverse().forEach(function(parent) {
[fromState].concat(fromState.parents).reverse().forEach(function(parent) {
if (root) return;
for (var param in paramDiff) {
if (parent.params[param] || parent.queryParams[param]) {
root = parent;
Expand Down
8 changes: 4 additions & 4 deletions dist/abyssa-with-deps.min.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions dist/abyssa.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*! @license
* abyssa <https://github.com/AlexGalays/abyssa-js/>
* Author: Alexandre Galays | MIT License
* v1.2.13 (2013-11-28T09:57:47.157Z)
* v1.2.14 (2013-12-04T14:13:38.914Z)
*/
(function () {
var factory = function (signals, crossroads, when, history) {
Expand Down Expand Up @@ -246,6 +246,7 @@ function doTransition(enters, exits, params) {

/**
* Finds the top-most current state's parent that must be exited.
* For paramOnlyChange, fromState is also checked for owning params.
*
* @param {Abyssa.State} fromState The original state.
* @param {Abyssa.State} toState The target state.
Expand All @@ -259,7 +260,8 @@ function transitionRoot(fromState, toState, paramOnlyChange, paramDiff) {

// For a param-only change, the root is the top-most state owning the param(s),
if (paramOnlyChange) {
fromState.parents.slice().reverse().forEach(function(parent) {
[fromState].concat(fromState.parents).reverse().forEach(function(parent) {
if (root) return;
for (var param in paramDiff) {
if (parent.params[param] || parent.queryParams[param]) {
root = parent;
Expand Down
4 changes: 2 additions & 2 deletions dist/abyssa.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description" : "A stateful router library for single page applications",
"keywords" : ["routes", "routing", "router", "hierarchical", "stateful"],
"homepage" : "https://github.com/AlexGalays/abyssa-js/",
"version" : "1.2.13",
"version" : "1.2.14",
"author" : {
"name" : "Alexandre Galays",
"url" : "https://github.com/AlexGalays/"
Expand Down
4 changes: 3 additions & 1 deletion src/Transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ function doTransition(enters, exits, params) {

/**
* Finds the top-most current state's parent that must be exited.
* For paramOnlyChange, fromState is also checked for owning params.
*
* @param {Abyssa.State} fromState The original state.
* @param {Abyssa.State} toState The target state.
Expand All @@ -124,7 +125,8 @@ function transitionRoot(fromState, toState, paramOnlyChange, paramDiff) {

// For a param-only change, the root is the top-most state owning the param(s),
if (paramOnlyChange) {
fromState.parents.slice().reverse().forEach(function(parent) {
[fromState].concat(fromState.parents).reverse().forEach(function(parent) {
if (root) return;
for (var param in paramDiff) {
if (parent.params[param] || parent.queryParams[param]) {
root = parent;
Expand Down
76 changes: 76 additions & 0 deletions test/all-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,82 @@ QUnit.asyncTest('Query-only transitions', function() {
});


QUnit.asyncTest('Param changes only in a child-most state should not trigger a parent transition', function() {

var events = [],
lastArticleId;

var router = Router({

blog: State('blog', {
enter: function() {
events.push('blogEnter');
},

exit: function() {
events.push('blogExit');
},


articles: State('articles/:id', {
enter: function(params) {
events.push('articlesEnter');
lastArticleId = params.id;
},

exit: function() {
events.push('articlesExit');
}

})

})

}).init('/blog/articles/33');


nextTick()
.then(changeParamOnly)
.then(stateWasReEntered)
.then(addQueryString)
.then(stateWasFullyReEntered)
.then(changeQueryStringValue)
.then(stateWasFullyReEntered)
.then(QUnit.start);


function changeParamOnly() {
router.state('/blog/articles/44');
events = [];
}

// The transition only goes up to the state owning the param
function stateWasReEntered() {
return nextTick().then(function() {
QUnit.assert.deepEqual(events, ['articlesExit', 'articlesEnter']);
events = [];
});
}

function addQueryString() {
router.state('/blog/articles/44?filter=1');
}

// By default, a change in the query will result in a complete transition to the root state and back.
function stateWasFullyReEntered() {
return nextTick().then(function() {
QUnit.assert.deepEqual(events, ['articlesExit', 'blogExit', 'blogEnter', 'articlesEnter']);
events = [];
});
}

function changeQueryStringValue() {
router.state('/blog/articles/44?filter=2');
}

});


QUnit.asyncTest('The query string is provided to all states', function() {

Router({
Expand Down

0 comments on commit f772f85

Please sign in to comment.