Skip to content

Commit 00966ec

Browse files
committed
feat(UrlMatcher): injectable functions as defaults
Default parameter values may now be specified as injectable functions.
1 parent 63607bd commit 00966ec

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

src/urlMatcherFactory.js

+25-4
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,19 @@ function UrlMatcher(pattern, config) {
8080
segments = this.segments = [],
8181
params = this.params = {};
8282

83+
/**
84+
* [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
85+
* default value, which may be the result of an injectable function.
86+
*/
87+
function $value(value) {
88+
/*jshint validthis: true */
89+
return isDefined(value) ? this.type.decode(value) : $UrlMatcherFactory.$$getDefaultValue(this);
90+
}
91+
8392
function addParameter(id, type, config) {
8493
if (!/^\w+(-+\w+)*$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
8594
if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
86-
params[id] = extend({ type: type || new Type() }, config);
95+
params[id] = extend({ type: type || new Type(), $value: $value }, config);
8796
}
8897

8998
function quoteRegExp(string, pattern, isOptional) {
@@ -216,7 +225,7 @@ UrlMatcher.prototype.exec = function (path, searchParams) {
216225
for (i = 0; i < nPath; i++) {
217226
param = params[i];
218227
cfg = this.params[param];
219-
values[param] = isDefined(m[i + 1]) ? cfg.type.decode(m[i + 1]) : cfg.value;
228+
values[param] = cfg.$value(m[i + 1]);
220229
}
221230
for (/**/; i < nTotal; i++) {
222231
param = params[i];
@@ -483,6 +492,19 @@ function $UrlMatcherFactory() {
483492
};
484493
}
485494

495+
function isInjectable(value) {
496+
return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1])));
497+
}
498+
499+
/**
500+
* [Internal] Get the default value of a parameter, which may be an injectable function.
501+
*/
502+
$UrlMatcherFactory.$$getDefaultValue = function(config) {
503+
if (!isInjectable(config.value)) return config.value;
504+
if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
505+
return injector.invoke(config.value);
506+
};
507+
486508
/**
487509
* @ngdoc function
488510
* @name ui.router.util.$urlMatcherFactory#caseInsensitive
@@ -683,8 +705,7 @@ function $UrlMatcherFactory() {
683705
if (UrlMatcher.prototype.$types[type.name]) {
684706
throw new Error("A type named '" + type.name + "' has already been defined.");
685707
}
686-
var isAnnotated = isFunction(type.def) || isArray(type.def);
687-
var def = new Type(isAnnotated ? injector.invoke(type.def) : type.def);
708+
var def = new Type(isInjectable(type.def) ? injector.invoke(type.def) : type.def);
688709
UrlMatcher.prototype.$types[type.name] = def;
689710
});
690711
}

test/urlMatcherFactorySpec.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,38 @@ describe("urlMatcherFactory", function () {
329329
expect(m.exec("/foo")).toEqual({ foo: "bar" });
330330
});
331331

332-
it("should populate default values for query params", function() {
332+
it("should populate query params", function() {
333333
var defaults = { order: "name", limit: 25, page: 1 };
334334
var m = new UrlMatcher('/foo?order&limit&page', {
335335
params: defaults
336336
});
337337
expect(m.exec("/foo")).toEqual(defaults);
338338
});
339+
340+
it("should allow function-calculated values", function() {
341+
var m = new UrlMatcher('/foo/:bar', {
342+
params: {
343+
bar: function() {
344+
return "Value from bar()";
345+
}
346+
}
347+
});
348+
expect(m.exec('/foo').bar).toBe("Value from bar()");
349+
});
350+
351+
it("should allow injectable functions", inject(function($stateParams) {
352+
var m = new UrlMatcher('/users/:user', {
353+
params: {
354+
user: function($stateParams) {
355+
return $stateParams.user;
356+
}
357+
}
358+
});
359+
var user = { name: "Bob" };
360+
361+
$stateParams.user = user;
362+
expect(m.exec('/users').user).toBe(user);
363+
}));
339364
});
340365
});
341366

0 commit comments

Comments
 (0)