1
1
/** @module params */ /** for typedoc */
2
- import { Type } from "./type" ;
2
+ import { ParamType } from "./type" ;
3
3
4
4
export interface RawParams {
5
5
[ key : string ] : any ;
@@ -86,12 +86,12 @@ export interface ParamDeclaration {
86
86
/**
87
87
* A property of [[ParamDeclaration]]:
88
88
*
89
- * Specifies the [[Type ]] of the parameter.
89
+ * Specifies the [[ParamType ]] of the parameter.
90
90
*
91
91
* Set this property to the name of parameter's type. The type may be either one of the
92
92
* built in types, or a custom type that has been registered with the [[$urlMatcherFactory]]
93
93
*/
94
- type : ( string | Type ) ;
94
+ type : ( string | ParamType ) ;
95
95
96
96
/**
97
97
* A property of [[ParamDeclaration]]:
@@ -106,7 +106,7 @@ export interface ParamDeclaration {
106
106
* then the value is treated as single value (e.g.: { foo: '1' }).
107
107
*
108
108
* If you specified a [[type]] for the parameter, the value will be treated as an array
109
- * of the specified Type .
109
+ * of the specified [[ParamType]] .
110
110
*
111
111
* @example
112
112
* ```
@@ -221,49 +221,195 @@ export interface Replace {
221
221
222
222
223
223
/**
224
- * Defines the behavior of a custom [[Type]].
224
+ * Definition for a custom [[ParamType]]
225
+ *
226
+ * A developer can create a custom parameter type definition to customize the encoding and decoding of parameter values.
227
+ * The definition should implement all the methods of this interface.
228
+ *
229
+ * Parameter values are parsed from the URL as strings.
230
+ * However, it is often useful to parse the string into some other form, such as:
231
+ *
232
+ * - integer
233
+ * - date
234
+ * - array of <integer/date/string>
235
+ * - custom object
236
+ * - some custom string representation
237
+ *
238
+ * Typed parameter definitions control how parameter values are encoded (to the URL) and decoded (from the URL).
239
+ * UI-Router always provides the decoded parameter values to the user from methods such as [[Transition.params]].
240
+ *
241
+ *
242
+ * For example, if a state has a url of `/foo/{fooId:int}` (the `fooId` parameter is of the `int` ParamType)
243
+ * and if the browser is at `/foo/123`, then the 123 is parsed as an integer:
244
+ *
245
+ * ```js
246
+ * var fooId = transition.params().fooId;
247
+ * fooId === "123" // false
248
+ * fooId === 123 // true
249
+ * ```
250
+ *
251
+ *
252
+ * #### Examples
253
+ *
254
+ * This example encodes an array of integers as a dash-delimited string to be used in the URL.
255
+ *
256
+ * If we call `$state.go('foo', { fooIds: [20, 30, 40] });`, the URL changes to `/foo/20-30-40`.
257
+ * If we navigate to `/foo/1-2-3`, the `foo` state's onEnter logs `[1, 2, 3]`.
258
+ *
259
+ * @example
260
+ * ```
261
+ *
262
+ * $urlMatcherFactoryProvider.type('intarray', {
263
+ * // Take an array of ints [1,2,3] and return a string "1-2-3"
264
+ * encode: (array) => array.join("-"),
265
+ *
266
+ * // Take an string "1-2-3" and return an array of ints [1,2,3]
267
+ * decode: (str) => str.split("-").map(x => parseInt(x, 10)),
268
+ *
269
+ * // Match the encoded string in the URL
270
+ * pattern: new RegExp("[0-9]+(?:-[0-9]+)*")
271
+ *
272
+ * // Ensure that the (decoded) object is an array, and that all its elements are numbers
273
+ * is: (obj) => Array.isArray(obj) &&
274
+ * obj.reduce((acc, item) => acc && typeof item === 'number', true),
275
+ *
276
+ * // Compare two arrays of integers
277
+ * equals: (array1, array2) => array1.length === array2.length &&
278
+ * array1.reduce((acc, item, idx) => acc && item === array2[idx], true);
279
+ * });
280
+ *
281
+ * $stateProvider.state('foo', {
282
+ * url: "/foo/{fooIds:intarray}",
283
+ * onEnter: function($transition$) {
284
+ * console.log($transition$.fooIds); // Logs "[1, 2, 3]"
285
+ * }
286
+ * });
287
+ * ```
288
+ *
289
+ *
290
+ * This example decodes an integer from the URL.
291
+ * It uses the integer as an index to look up an item from a static list.
292
+ * That item from the list is the decoded parameter value.
293
+ *
294
+ * @example
295
+ * ```
296
+ *
297
+ * var list = ['John', 'Paul', 'George', 'Ringo'];
298
+ *
299
+ * $urlMatcherFactoryProvider.type('listItem', {
300
+ * encode: function(item) {
301
+ * // Represent the list item in the URL using its corresponding index
302
+ * return list.indexOf(item);
303
+ * },
304
+ * decode: function(item) {
305
+ * // Look up the list item by index
306
+ * return list[parseInt(item, 10)];
307
+ * },
308
+ * is: function(item) {
309
+ * // Ensure the item is valid by checking to see that it appears
310
+ * // in the list
311
+ * return list.indexOf(item) > -1;
312
+ * }
313
+ * });
314
+ *
315
+ * $stateProvider.state('list', {
316
+ * url: "/list/{item:listItem}",
317
+ * controller: function($scope, $stateParams) {
318
+ * console.log($stateParams.item);
319
+ * }
320
+ * });
321
+ *
322
+ * // ...
323
+ *
324
+ * // Changes URL to '/list/3', logs "Ringo" to the console
325
+ * $state.go('list', { item: "Ringo" });
326
+ * ```
327
+ *
225
328
* See: [[UrlMatcherFactory.type]]
226
329
*/
227
- export interface TypeDefinition {
330
+ export interface ParamTypeDefinition {
228
331
/**
229
- * Detects whether a value is of a particular type. Accepts a native (decoded) value
230
- * and determines whether it matches the current `Type` object.
332
+ * Tests if some object type is compatible with this parameter type
333
+ *
334
+ * Detects whether some value is of this particular type.
335
+ * Accepts a decoded value and determines whether it matches this `ParamType` object.
336
+ *
337
+ * If your custom type encodes the parameter to a specific type, check for that type here.
338
+ * For example, if your custom type decodes the URL parameter value as an array of ints, return true if the
339
+ * input is an array of ints:
340
+ * `(val) => Array.isArray(val) && array.reduce((acc, x) => acc && parseInt(val, 10) === val, true)`.
341
+ * If your type decodes the URL parameter value to a custom string, check that the string matches
342
+ * the pattern (don't use an arrow fn if you need `this`): `function (val) { return !!this.pattern.exec(val) }`
343
+ *
344
+ * Note: This method is _not used to check if the URL matches_.
345
+ * It's used to check if a _decoded value is this type_.
346
+ * Use [[pattern]] to check the URL.
231
347
*
232
348
* @param val The value to check.
233
349
* @param key If the type check is happening in the context of a specific [[UrlMatcher]] object,
234
350
* this is the name of the parameter in which `val` is stored. Can be used for
235
- * meta-programming of `Type ` objects.
351
+ * meta-programming of `ParamType ` objects.
236
352
* @returns `true` if the value matches the type, otherwise `false`.
237
353
*/
238
354
is ( val : any , key ?: string ) : boolean ;
239
355
240
356
/**
241
- * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the
242
- * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it
243
- * only needs to be a representation of `val` that has been coerced to a string.
357
+ * Encodes a custom/native type value to a string that can be embedded in a URL.
358
+ *
359
+ * Note that the return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it
360
+ * only needs to be a representation of `val` that has been encoded as a string.
361
+ *
362
+ * For example, if your type decodes to an array of ints, then encode the array of ints as a string here:
363
+ * `(intarray) => intarray.join("-")`
364
+ *
365
+ * Note: in general, [[encode]] and [[decode]] should be symmetrical. That is, `encode(decode(str)) === str`
244
366
*
245
367
* @param val The value to encode.
246
- * @param key The name of the parameter in which `val` is stored. Can be used for meta-programming of `Type ` objects.
368
+ * @param key The name of the parameter in which `val` is stored. Can be used for meta-programming of `ParamType ` objects.
247
369
* @returns a string representation of `val` that can be encoded in a URL.
248
370
*/
249
371
encode ( val : any , key ?: string ) : ( string | string [ ] ) ;
250
372
251
373
/**
252
- * Converts a parameter value (from URL string or transition param) to a custom/native value.
374
+ * Decodes a parameter value string (from URL string or transition param) to a custom/native value.
375
+ *
376
+ * For example, if your type decodes to an array of ints, then decode the string as an array of ints here:
377
+ * `(str) => str.split("-").map(str => parseInt(str, 10))`
378
+ *
379
+ * Note: in general, [[encode]] and [[decode]] should be symmetrical. That is, `encode(decode(str)) === str`
253
380
*
254
381
* @param val The URL parameter value to decode.
255
- * @param key The name of the parameter in which `val` is stored. Can be used for meta-programming of `Type ` objects.
382
+ * @param key The name of the parameter in which `val` is stored. Can be used for meta-programming of `ParamType ` objects.
256
383
* @returns a custom representation of the URL parameter value.
257
384
*/
258
385
decode ( val : string , key ?: string ) : any ;
259
386
260
387
/**
261
388
* Determines whether two decoded values are equivalent.
262
389
*
390
+ * For example, if your type decodes to an array of ints, then check if the arrays are equal:
391
+ * `(a, b) => a.length === b.length && a.reduce((acc, x, idx) => acc && x === b[idx], true)`
392
+ *
263
393
* @param a A value to compare against.
264
394
* @param b A value to compare against.
265
395
* @returns `true` if the values are equivalent/equal, otherwise `false`.
266
396
*/
267
397
equals ( a : any , b : any ) : boolean ;
398
+
399
+ /**
400
+ * A regular expression that matches the encoded parameter type
401
+ *
402
+ * This regular expression is used to match the parameter type in the URL.
403
+ *
404
+ * For example, if your type encodes as a dash-separated numbers, match that here:
405
+ * `new RegExp("[0-9]+(?:-[0-9]+)*")`.
406
+ *
407
+ * There are some limitations to these regexps:
408
+ *
409
+ * - No capturing groups are allowed (use non-capturing groups: `(?: )`)
410
+ * - No pattern modifiers like case insensitive
411
+ * - No start-of-string or end-of-string: `/^foo$/`
412
+ */
413
+ pattern : RegExp ;
268
414
}
269
415
0 commit comments