Skip to content

Commit

Permalink
Merge pull request angular-ui#1032 from angular-ui/types
Browse files Browse the repository at this point in the history
Typed and optional parameters
  • Loading branch information
nateabele committed Apr 19, 2014
2 parents 2aede6e + 7ef8f3c commit ed844c6
Show file tree
Hide file tree
Showing 8 changed files with 1,066 additions and 276 deletions.
24 changes: 4 additions & 20 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function ancestors(first, second) {
* @param {Object} object A JavaScript object.
* @return {Array} Returns the keys of the object as an array.
*/
function keys(object) {
function objectKeys(object) {
if (Object.keys) {
return Object.keys(object);
}
Expand Down Expand Up @@ -96,8 +96,9 @@ function inheritParams(currentParams, newParams, $current, $to) {
var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];

for (var i in parents) {
if (!parents[i].params || !parents[i].params.length) continue;
parentParams = parents[i].params;
if (!parents[i].params) continue;
parentParams = objectKeys(parents[i].params);
if (!parentParams.length) continue;

for (var j in parentParams) {
if (arraySearch(inheritList, parentParams[j]) >= 0) continue;
Expand All @@ -108,23 +109,6 @@ function inheritParams(currentParams, newParams, $current, $to) {
return extend({}, inherited, newParams);
}

/**
* Normalizes a set of values to string or `null`, filtering them by a list of keys.
*
* @param {Array} keys The list of keys to normalize/return.
* @param {Object} values An object hash of values to normalize.
* @return {Object} Returns an object hash of normalized string values.
*/
function normalize(keys, values) {
var normalized = {};

forEach(keys, function (name) {
var value = values[name];
normalized[name] = (value != null) ? String(value) : null;
});
return normalized;
}

/**
* Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
*
Expand Down
53 changes: 28 additions & 25 deletions src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,14 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {

// Build a URLMatcher if necessary, either via a relative or absolute URL
url: function(state) {
var url = state.url;
var url = state.url, config = { params: state.params || {} };

if (isString(url)) {
if (url.charAt(0) == '^') {
return $urlMatcherFactory.compile(url.substring(1));
}
return (state.parent.navigable || root).url.concat(url);
if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config);
return (state.parent.navigable || root).url.concat(url, config);
}

if ($urlMatcherFactory.isMatcher(url) || url == null) {
return url;
}
if (!url || $urlMatcherFactory.isMatcher(url)) return url;
throw new Error("Invalid url '" + url + "' in state '" + state + "'");
},

Expand All @@ -71,10 +67,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
// Derive parameters for this state and ensure they're a super-set of parent's parameters
params: function(state) {
if (!state.params) {
return state.url ? state.url.parameters() : state.parent.params;
return state.url ? state.url.params : state.parent.params;
}
if (!isArray(state.params)) throw new Error("Invalid params in state '" + state + "'");
if (state.url) throw new Error("Both params and url specicified in state '" + state + "'");
return state.params;
},

Expand All @@ -94,16 +88,18 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
},

ownParams: function(state) {
state.params = state.params || {};

if (!state.parent) {
return state.params;
return objectKeys(state.params);
}
var paramNames = {}; forEach(state.params, function (p) { paramNames[p] = true; });
var paramNames = {}; forEach(state.params, function (v, k) { paramNames[k] = true; });

forEach(state.parent.params, function (p) {
if (!paramNames[p]) {
throw new Error("Missing required parameter '" + p + "' in state '" + state.name + "'");
forEach(state.parent.params, function (v, k) {
if (!paramNames[k]) {
throw new Error("Missing required parameter '" + k + "' in state '" + state.name + "'");
}
paramNames[p] = false;
paramNames[k] = false;
});
var ownParams = [];

Expand Down Expand Up @@ -782,8 +778,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
toState = findState(to, options.relative);

if (!isDefined(toState)) {
if (options.relative) throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
throw new Error("No such state '" + to + "'");
if (!options.relative) throw new Error("No such state '" + to + "'");
throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'");
}
}
if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
Expand All @@ -808,14 +804,14 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
// TODO: We may not want to bump 'transition' if we're called from a location change
// that we've initiated ourselves, because we might accidentally abort a legitimate
// transition initiated from code?
if (shouldTriggerReload(to, from, locals, options) ) {
if (shouldTriggerReload(to, from, locals, options)) {
if (to.self.reloadOnSearch !== false) $urlRouter.update();
$state.transition = null;
return $q.when($state.current);
}

// Normalize/filter parameters before we pass them to event handlers etc.
toParams = normalize(to.params, toParams || {});
// Filter parameters before we pass them to event handlers etc.
toParams = filterByKeys(objectKeys(to.params), toParams || {});

// Broadcast start event and cancel the transition if requested
if (options.notify) {
Expand Down Expand Up @@ -1090,7 +1086,12 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
* @returns {string} compiled state url
*/
$state.href = function href(stateOrName, params, options) {
options = extend({ lossy: true, inherit: false, absolute: false, relative: $state.$current }, options || {});
options = extend({
lossy: true,
inherit: false,
absolute: false,
relative: $state.$current
}, options || {});

var state = findState(stateOrName, options.relative);

Expand All @@ -1102,7 +1103,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
if (!nav || !nav.url) {
return null;
}
return $urlRouter.href(nav.url, normalize(state.params, params || {}), { absolute: options.absolute });
return $urlRouter.href(nav.url, filterByKeys(objectKeys(state.params), params || {}), {
absolute: options.absolute
});
};

/**
Expand Down Expand Up @@ -1132,7 +1135,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
// necessary. In addition to being available to the controller and onEnter/onExit callbacks,
// we also need $stateParams to be available for any $injector calls we make during the
// dependency resolution process.
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params, params);
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(objectKeys(state.params), params);
var locals = { $stateParams: $stateParams };

// Resolve 'global' dependencies for the state, i.e. those not specific to a view.
Expand Down
Loading

0 comments on commit ed844c6

Please sign in to comment.