Skip to content
This repository has been archived by the owner on Sep 20, 2020. It is now read-only.

Commit

Permalink
fix(dsr): Allow default substates and parameters for deep state redir…
Browse files Browse the repository at this point in the history
…ect.

 Closes #150
  • Loading branch information
christopherthielen committed Feb 1, 2015
1 parent 9233ea9 commit 20fade7
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
33 changes: 23 additions & 10 deletions src/dsr.js
Expand Up @@ -43,14 +43,19 @@ angular.module('ct.ui.router.extras.dsr').service("$deepStateRedirect", [ '$root
}

function getConfig(state) {
var declaration = state.deepStateRedirect;
var declaration = state.deepStateRedirect || state.dsr;
if (!declaration) return { dsr: false };
var dsrCfg = { dsr: true };

if (angular.isFunction(declaration))
if (angular.isFunction(declaration)) {
dsrCfg.fn = declaration;
else if (angular.isObject(declaration))
} else if (angular.isObject(declaration)) {
dsrCfg = angular.extend(dsrCfg, declaration);
}

if (angular.isString(dsrCfg.default)) {
dsrCfg.default = { state: dsrCfg.default };
}

if (!dsrCfg.fn) {
dsrCfg.fn = [ '$dsr$', function($dsr$) {
Expand Down Expand Up @@ -80,23 +85,30 @@ angular.module('ct.ui.router.extras.dsr').service("$deepStateRedirect", [ '$root
return deepStateRedirectsByName[state.name] || false;
}

function getParamsString(params, dsrParams) {
function safeString(input) { return !input ? input : input.toString(); }
function getMatchParams(params, dsrParams) {
if (dsrParams === true) dsrParams = Object.keys(params);
if (dsrParams === null || dsrParams === undefined) dsrParams = [];

var matchParams = {};
angular.forEach(dsrParams.sort(), function(name) { matchParams[name] = params[name]; });
return matchParams;
}

function getParamsString(params, dsrParams) {
var matchParams = getMatchParams(params, dsrParams);
function safeString(input) { return !input ? input : input.toString(); }
var paramsToString = {};
angular.forEach(dsrParams.sort(), function(name) { paramsToString[name] = safeString(params[name]); });
angular.forEach(matchParams, function(val, name) { paramsToString[name] = safeString(val); });
return angular.toJson(paramsToString);
}

$rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
if (ignoreDsr || computeDeepStateStatus(toState) !== REDIRECT) return;
var cfg = getConfig(toState);
if (ignoreDsr || (computeDeepStateStatus(toState) !== REDIRECT) && !cfg.default) return;
// We're changing directly to one of the redirect (tab) states.
// Get the DSR key for this state by calculating the DSRParams option
var cfg = getConfig(toState);
var key = getParamsString(toParams, cfg.params);
var redirect = lastSubstate[toState.name][key];
var redirect = lastSubstate[toState.name][key] || cfg.default;
if (!redirect) return;

// we have a last substate recorded
Expand All @@ -105,7 +117,8 @@ angular.module('ct.ui.router.extras.dsr').service("$deepStateRedirect", [ '$root
if (!result) return;
if (result.state) redirect = result;
event.preventDefault();
$state.go(redirect.state, redirect.params);
var redirectParams = getMatchParams(toParams, cfg.params);
$state.go(redirect.state, angular.extend(redirectParams, redirect.params));
});

$rootScope.$on("$stateChangeSuccess", function (event, toState, toParams, fromState, fromParams) {
Expand Down
31 changes: 30 additions & 1 deletion test/dsrSpec.js
Expand Up @@ -16,7 +16,16 @@ function getDSRStates () {
{ name: 'p2', url: '/p2/:param1/:param2', deepStateRedirect: { params: true } },
{ name: 'p2.child' },
{ name: 'p3', url: '/p3/:param1', deepStateRedirect: { params: true } },
{ name: 'p3.child'}
{ name: 'p3.child'},
{ name: 'p4', url: '/p4', dsr: { default: "p4.child" } },
{ name: 'p4.child'},
{ name: 'p4.child2'},
{ name: 'p5', url: '/p5', dsr: { default: { state: "p5.child", params: { p5param: "1" } } } },
{ name: 'p5.child', url: '/child/:p5param'},
{ name: 'p6', url: '/p6/:param', dsr: { params: true, default: "p6.child1" } },
{ name: 'p6.child1'},
{ name: 'p6.child2'},
{ name: 'p6.child3'}
];
}

Expand Down Expand Up @@ -155,4 +164,24 @@ describe('deepStateRedirect', function () {
expect($state.current.name).toBe("tabs.tabs1");
});
});

describe("default substates", function() {
it("should affect the first transition to the DSR state", function() {
testGo("p4", undefined, { redirect: 'p4.child'});
testGo("p4.child2");
testGo("p4", undefined, { redirect: 'p4.child2'});
});

it("should provide default parameters", function() {
testGo("p5", undefined, { redirect: 'p5.child'});
expect($state.params).toEqual({p5param: "1"});
});

it("should redirect to the default state when params: true and transition to DSR with un-seen param values", function() {
testGo("p6", undefined, { params: {param: "1"}, redirect: 'p6.child1'});
testGo("p6.child2");
testGo("p6", undefined, { params: {param: "1"}, redirect: 'p6.child2'});
testGo("p6", undefined, { params: {param: "2"}, redirect: 'p6.child1'});
});
})
});

0 comments on commit 20fade7

Please sign in to comment.