Skip to content

Commit 7186651

Browse files
committed
Merge pull request #1443 from christopherthielen/default-type-coersion
Fixes for Typed Params
2 parents 6097343 + 97f8d90 commit 7186651

File tree

6 files changed

+344
-122
lines changed

6 files changed

+344
-122
lines changed

src/common.js

+14
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ function objectKeys(object) {
6161
return result;
6262
}
6363

64+
/**
65+
* like objectKeys, but includes keys from prototype chain.
66+
* @param object the object whose prototypal keys will be returned
67+
* @param ignoreKeys an array of keys to ignore
68+
*/
69+
function protoKeys(object, ignoreKeys) {
70+
var result = [];
71+
for (var key in object) {
72+
if (!ignoreKeys || ignoreKeys.indexOf(key) === -1)
73+
result.push(key);
74+
}
75+
return result;
76+
}
77+
6478
/**
6579
* IE8-safe wrapper for `Array.prototype.indexOf()`.
6680
*

src/state.js

+34-39
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider'];
2323
function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
2424

25-
var root, states = {}, $state, queue = {}, abstractKey = 'abstract';
25+
var root, states = {}, $state, queue = {}, abstractKey = 'abstract', isRuntime = false;
2626

2727
// Builds state properties from definition passed to registerState()
2828
var stateBuilder = {
@@ -64,12 +64,19 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
6464
return state.url ? state : (state.parent ? state.parent.navigable : null);
6565
},
6666

67+
// Own parameters for this state. state.url.params is already built at this point. Create and add non-url params
68+
ownParams: function(state) {
69+
var params = state.url && state.url.params || new $$UMFP.ParamSet();
70+
forEach(state.params || {}, function(config, id) {
71+
if (!params[id]) params[id] = new $$UMFP.Param(id, null, config);
72+
});
73+
return params;
74+
},
75+
6776
// Derive parameters for this state and ensure they're a super-set of parent's parameters
6877
params: function(state) {
69-
if (!state.params) {
70-
return state.url ? state.url.params : state.parent.params;
71-
}
72-
return state.params;
78+
var parentParams = state.parent && state.parent.params || new $$UMFP.ParamSet();
79+
return inherit(parentParams, state.ownParams);
7380
},
7481

7582
// If there is no explicit multi-view configuration, make one up so we don't have
@@ -87,28 +94,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
8794
return views;
8895
},
8996

90-
ownParams: function(state) {
91-
state.params = state.params || {};
92-
93-
if (!state.parent) {
94-
return objectKeys(state.params);
95-
}
96-
var paramNames = {}; forEach(state.params, function (v, k) { paramNames[k] = true; });
97-
98-
forEach(state.parent.params, function (v, k) {
99-
if (!paramNames[k]) {
100-
throw new Error("Missing required parameter '" + k + "' in state '" + state.name + "'");
101-
}
102-
paramNames[k] = false;
103-
});
104-
var ownParams = [];
105-
106-
forEach(paramNames, function (own, p) {
107-
if (own) ownParams.push(p);
108-
});
109-
return ownParams;
110-
},
111-
11297
// Keep a full path from the root down to this state as this is needed for state activation.
11398
path: function(state) {
11499
return state.parent ? state.parent.path.concat(state) : []; // exclude root from path
@@ -171,6 +156,13 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
171156
queue[parentName].push(state);
172157
}
173158

159+
function flushQueuedChildren(parentName) {
160+
var queued = queue[parentName] || [];
161+
while(queued.length) {
162+
registerState(queued.shift());
163+
}
164+
}
165+
174166
function registerState(state) {
175167
// Wrap a new object around the state so we can store our private details easily.
176168
state = inherit(state, {
@@ -186,10 +178,11 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
186178
// Get parent name
187179
var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.'))
188180
: (isString(state.parent)) ? state.parent
181+
: (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name
189182
: '';
190183

191184
// If parent is not registered yet, add state to queue and register later
192-
if (parentName && !states[parentName]) {
185+
if (name !== "" && (!isRuntime || !states[parentName])) {
193186
return queueState(parentName, state.self);
194187
}
195188

@@ -208,11 +201,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
208201
}
209202

210203
// Register any queued children
211-
if (queue[name]) {
212-
for (var i = 0; i < queue[name].length; i++) {
213-
registerState(queue[name][i]);
214-
}
215-
}
204+
flushQueuedChildren(name);
216205

217206
return state;
218207
}
@@ -538,8 +527,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
538527
* you're coming from.
539528
*/
540529
this.$get = $get;
541-
$get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter'];
542-
function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter) {
530+
$get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory'];
531+
function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) {
543532

544533
var TransitionSuperseded = $q.reject(new Error('transition superseded'));
545534
var TransitionPrevented = $q.reject(new Error('transition prevented'));
@@ -793,6 +782,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
793782
}
794783
if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
795784
if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
785+
if (!toState.params.$$validates(toParams)) return TransitionFailed;
786+
787+
toParams = toState.params.$$values(toParams);
796788
to = toState;
797789

798790
var toPath = to.path;
@@ -801,7 +793,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
801793
var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];
802794

803795
if (!options.reload) {
804-
while (state && state === fromPath[keep] && equalForKeys(toParams, fromParams, state.ownParams)) {
796+
while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {
805797
locals = toLocals[keep] = state.locals;
806798
keep++;
807799
state = toPath[keep];
@@ -820,7 +812,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
820812
}
821813

822814
// Filter parameters before we pass them to event handlers etc.
823-
toParams = filterByKeys(objectKeys(to.params), toParams || {});
815+
toParams = filterByKeys(to.params.$$keys(), toParams || {});
824816

825817
// Broadcast start event and cancel the transition if requested
826818
if (options.notify) {
@@ -1133,7 +1125,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
11331125
if (!nav || nav.url === undefined || nav.url === null) {
11341126
return null;
11351127
}
1136-
return $urlRouter.href(nav.url, filterByKeys(objectKeys(state.params), params || {}), {
1128+
return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys(), params || {}), {
11371129
absolute: options.absolute
11381130
});
11391131
};
@@ -1162,7 +1154,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
11621154
// necessary. In addition to being available to the controller and onEnter/onExit callbacks,
11631155
// we also need $stateParams to be available for any $injector calls we make during the
11641156
// dependency resolution process.
1165-
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(objectKeys(state.params), params);
1157+
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
11661158
var locals = { $stateParams: $stateParams };
11671159

11681160
// Resolve 'global' dependencies for the state, i.e. those not specific to a view.
@@ -1203,6 +1195,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
12031195
});
12041196
}
12051197

1198+
isRuntime = true;
1199+
flushQueuedChildren("");
1200+
12061201
return $state;
12071202
}
12081203

0 commit comments

Comments
 (0)