UNPKG

20.9 kBTypeScriptView Raw
1import { ParamType } from './paramType';
2/**
3 * Parameter values
4 *
5 * An object containing state parameter key/value pairs
6 *
7 * #### Example:
8 * ```js
9 * {
10 * userId: 353474,
11 * folderId: 'inbox'
12 * }
13 * ```
14 */
15export interface RawParams {
16 [key: string]: any;
17}
18/**
19 * Configuration for a single Parameter
20 *
21 * In a [[StateDeclaration.params]], each `ParamDeclaration`
22 * defines how a single State Parameter should work.
23 *
24 * #### Example:
25 * ```js
26 * var mystate = {
27 * template: '<div ui-view/>',
28 * controller: function() {}
29 * url: '/mystate/:start?{count:int}',
30 * params: {
31 * start: { // <-- ParamDeclaration for `start`
32 * type: 'date',
33 * value: new Date(), // <-- Default value
34 * squash: true,
35 * },
36 *
37 * nonUrlParam: { // <-- ParamDeclaration for 'nonUrlParam'
38 * type: "int",
39 * array: true,
40 * value: []
41 * },
42 *
43 * count: 0, // <-- Default value for 'param1'
44 * // (shorthand ParamDeclaration.value)
45 * }
46 * }
47 * ```
48 */
49export interface ParamDeclaration {
50 /**
51 * The default value for this parameter.
52 *
53 * Specifies the default value for this parameter.
54 * This implicitly sets this parameter as optional.
55 *
56 * When UI-Router routes to a state and no value is specified for this parameter in the URL or transition,
57 * the default value will be used instead.
58 * If value is a function, it will be injected and invoked, and the return value used.
59 *
60 * Note: `value: undefined` is treated as though **no default value was specified**, while `value: null` is treated
61 * as **"the default value is null"**.
62 *
63 * ```
64 * // define default values for param1 and param2
65 * params: {
66 * param1: {
67 * value: "defaultValue"
68 * },
69 * param2: {
70 * value: "param2Default;
71 * }
72 * }
73 * ```
74 *
75 * ### Shorthand Declaration
76 *
77 * If you only want to set the default value of the parameter, you may use a shorthand syntax.
78 * In the params map, instead mapping the param name to a full parameter configuration object, simply set map it
79 * to the default parameter value, e.g.:
80 * ```
81 * // Normal (non-shorthand) default value syntax
82 * params: {
83 * param1: {
84 * value: "defaultValue"
85 * },
86 * param2: {
87 * value: "param2Default"
88 * }
89 * }
90 *
91 * // Shorthand default value syntax
92 * params: {
93 * param1: "defaultValue",
94 * param2: "param2Default"
95 * }
96 * ```
97 *
98 * This defines a default value for the parameter.
99 * If a parameter value is `undefined`, this default value will be used instead
100 *
101 * ---
102 *
103 * Default: `undefined`
104 */
105 value?: any;
106 /**
107 * The parameter's type
108 *
109 * Specifies the [[ParamType]] of the parameter.
110 * Parameter types can be used to customize the encoding/decoding of parameter values.
111 *
112 * Set this property to the name of parameter's type.
113 * The type may be either one of the built in types, or a custom type that has been registered with the [[UrlMatcherFactory]].
114 *
115 * See [[ParamTypes]] for the list of built in types.
116 *
117 * ---
118 *
119 * Default:
120 * - Path parameters (`/:fooParam`): `path`
121 * - Query parameters (`?queryParam`): `query`
122 * - Non-url parameters (`param: { foo: null }`): `any`
123 *
124 */
125 type?: string | ParamType;
126 /**
127 * The parameter's `array` mode
128 *
129 * Explicitly specifies the array mode of a URL parameter
130 *
131 * - If `false`, the parameter value will be treated (encoded/decoded) as a single value
132 * - If `true`, the parameter value will be treated (encoded/decoded) as an array of values.
133 * - If `auto` (for query parameters only), if multiple values for a single parameter are present
134 * in the URL (e.g.: /foo?bar=1&bar=2&bar=3) then the values are mapped to an array (e.g.:
135 * `{ foo: [ '1', '2', '3' ] }`). However, if only one value is present (e.g.: /foo?bar=1)
136 * then the value is treated as single value (e.g.: { foo: '1' }).
137 *
138 * If you specified a [[type]] for the parameter, the value will be treated as an array
139 * of the specified [[ParamType]].
140 *
141 * #### Example:
142 * ```js
143 * {
144 * name: 'foo',
145 * url: '/foo/{arrayParam:int}`,
146 * params: {
147 * arrayParam: { array: true }
148 * }
149 * }
150 *
151 * // After the transition, URL should be '/foo/1-2-3'
152 * $state.go("foo", { arrayParam: [ 1, 2, 3 ] });
153 * ```
154 *
155 * @default `false` for path parameters, such as `url: '/foo/:pathParam'`
156 * @default `auto` for query parameters, such as `url: '/foo?queryParam'`
157 * @default `true` if the parameter name ends in `[]`, such as `url: '/foo/{implicitArrayParam:int[]}'`
158 */
159 array?: boolean;
160 /**
161 * Squash mode: omit default parameter values in URL
162 *
163 * Configures how a default parameter value is represented in the URL when the current parameter value
164 * is the same as the default value.
165 *
166 * There are three squash settings:
167 *
168 * - `false`: The parameter's default value is not squashed. It is encoded and included in the URL
169 * - `true`: The parameter's default value is omitted from the URL.
170 * If the parameter is preceeded and followed by slashes in the state's url declaration, then one of those slashes are omitted.
171 * This can allow for cleaner looking URLs.
172 * - `"&lt;arbitrary string&gt;"`: The parameter's default value is replaced with an arbitrary
173 * placeholder of your choice.
174 *
175 * #### Example:
176 * ```js
177 * {
178 * name: 'mystate',
179 * url: '/mystate/:myparam',
180 * params: {
181 * myparam: 'defaultParamValue'
182 * squash: true
183 * }
184 * }
185 *
186 * // URL will be `/mystate/`
187 * $state.go('mystate', { myparam: 'defaultParamValue' });
188 *
189 * // URL will be `/mystate/someOtherValue`
190 * $state.go('mystate', { myparam: 'someOtherValue' });
191 * ```
192 *
193 * #### Example:
194 * ```js
195 * {
196 * name: 'mystate2',
197 * url: '/mystate2/:myparam2',
198 * params: {
199 * myparam2: 'defaultParamValue'
200 * squash: "~"
201 * }
202 * }
203 *
204 * // URL will be `/mystate/~`
205 * $state.go('mystate', { myparam2: 'defaultParamValue' });
206 *
207 * // URL will be `/mystate/someOtherValue`
208 * $state.go('mystate', { myparam2: 'someOtherValue' });
209 * ```
210 *
211 * Default: If squash is not set, it uses the configured default squash policy. (See [[defaultSquashPolicy]]())
212 */
213 squash?: boolean | string;
214 /**
215 * @internal
216 *
217 * An array of [[Replace]] objects.
218 *
219 * When creating a Transition, defines how to handle certain special values, such as `undefined`, `null`,
220 * or empty string `""`. If the transition is started, and the parameter value is equal to one of the "to"
221 * values, then the parameter value is replaced with the "from" value.
222 *
223 * #### Example:
224 * ```js
225 * replace: [
226 * { from: undefined, to: null },
227 * { from: "", to: null }
228 * ]
229 * ```
230 */
231 replace?: Replace[];
232 /**
233 * @internal
234 * @internal
235 *
236 * This is not part of the declaration; it is a calculated value depending on if a default value was specified or not.
237 */
238 isOptional?: boolean;
239 /**
240 * Dynamic flag
241 *
242 * When `dynamic` is `true`, changes to the parameter value will not cause the state to be entered/exited.
243 * The resolves will not be re-fetched, nor will views be reloaded.
244 *
245 * Normally, if a parameter value changes, the state which declared that the parameter will be reloaded (entered/exited).
246 * When a parameter is `dynamic`, a transition still occurs, but it does not cause the state to exit/enter.
247 *
248 * This can be useful to build UI where the component updates itself when the param values change.
249 * A common scenario where this is useful is searching/paging/sorting.
250 *
251 * ---
252 *
253 * Note: this value overrides the `dynamic` value on a custom parameter type ([[ParamTypeDefinition.dynamic]]).
254 *
255 * ---
256 *
257 * Default: `false`
258 */
259 dynamic?: boolean;
260 /**
261 * Disables url-encoding of parameter values
262 *
263 * When `true`, parameter values are not url-encoded.
264 * This is commonly used to allow "slug" urls, with a parameter value including non-semantic slashes.
265 *
266 * #### Example:
267 * ```js
268 * url: '/product/:slug',
269 * params: {
270 * slug: { type: 'string', raw: true }
271 * }
272 * ```
273 *
274 * This allows a URL parameter of `{ slug: 'camping/tents/awesome_tent' }`
275 * to serialize to `/product/camping/tents/awesome_tent`
276 * instead of `/product/camping%2Ftents%2Fawesome_tent`.
277 *
278 * ---
279 *
280 * Note: this value overrides the `raw` value on a custom parameter type ([[ParamTypeDefinition.raw]]).
281 *
282 * ### Decoding warning
283 *
284 * The decoding behavior of raw parameters is not defined.
285 * For example, given a url template such as `/:raw1/:raw2`
286 * the url `/foo/bar/baz/qux/`, there is no way to determine which slashes belong to which params.
287 *
288 * It's generally safe to use a raw parameter at the end of a path, like '/product/:slug'.
289 * However, beware of the characters you allow in your raw parameter values.
290 * Avoid unencoded characters that could disrupt normal URL parsing, such as `?` and `#`.
291 *
292 * ---
293 *
294 * Default: `false`
295 */
296 raw?: boolean;
297 /**
298 * Enables/disables inheriting of this parameter's value
299 *
300 * When a transition is run with [[TransitionOptions.inherit]] set to
301 * `true`, the current param values are inherited in the new transition.
302 * However, parameters values which have `inherit: false` set will *not be inherited*.
303 *
304 * #### Example state :
305 * ```js
306 * var fooState = {
307 * name: 'foo',
308 * url: '/:fooId?mode&refresh',
309 * params: {
310 * refresh: { inherit: false }
311 * }
312 * }
313 *
314 * // Set fooId to 123
315 * $state.go('fooState', { fooId: 1234, mode: 'list', refresh: true });
316 * ```
317 *
318 * In the component:
319 * `mode: 'list' is inherited, but refresh: true is not inherited.
320 * // The param values are thus: `{ fooId: 4567, mode: 'list' }`
321 * ```
322 * <ui-sref="foo({ fooId: 4567 })">4567</ui-sref>
323 * ```
324 *
325 * ---
326 *
327 * See also [[TransitionOptions.inherit]] and [[ParamTypeDefinition.inherit]]
328 *
329 * ---
330 *
331 * Default: `true`
332 */
333 inherit?: boolean;
334}
335/**
336 * String replacement
337 *
338 * Represents an exact match string replacement.
339 *
340 * Note: `to` or `from` may be null or undefined, and will be tested using `===`.
341 */
342export interface Replace {
343 /**
344 * The value to replace.
345 *
346 * May be `null` or `undefined`.
347 * The entire value must match using `===`.
348 * When found, the [[to]] value is used instead.
349 */
350 from: string;
351 /**
352 * The new value
353 *
354 * Used instead of the [[from]] value.
355 */
356 to: string;
357}
358/**
359 * Describes a custom [[ParamType]]
360 *
361 * See: [[UrlMatcherFactory.type]]
362 *
363 * A developer can create a custom parameter type definition to customize the encoding and decoding of parameter values.
364 * The definition should implement all the methods of this interface.
365 *
366 * Parameter values are parsed from the URL as strings.
367 * However, it is often useful to parse the string into some other form, such as:
368 *
369 * - integer
370 * - date
371 * - array of <integer/date/string>
372 * - custom object
373 * - some internal string representation
374 *
375 * Typed parameter definitions control how parameter values are encoded (to the URL) and decoded (from the URL).
376 * UI-Router always provides the decoded parameter values to the user (from methods such as [[Transition.params]])).
377 *
378 * For example, if a state has a url of `/foo/{fooId:int}` (the `fooId` parameter is of the `int` ParamType)
379 * and if the browser is at `/foo/123`, then the 123 is parsed as an integer:
380 *
381 * ```js
382 * var fooId = transition.params().fooId;
383 * fooId === "123" // false
384 * fooId === 123 // true
385 * ```
386 *
387 *
388 * #### Examples
389 *
390 * This example encodes an array of integers as a dash-delimited string to be used in the URL.
391 *
392 * If we call `$state.go('foo', { fooIds: [20, 30, 40] });`, the URL changes to `/foo/20-30-40`.
393 * If we navigate to `/foo/1-2-3`, the `foo` state's onEnter logs `[1, 2, 3]`.
394 *
395 * @example
396 * ```
397 *
398 * $urlMatcherFactoryProvider.type('intarray', {
399 * // Take an array of ints [1,2,3] and return a string "1-2-3"
400 * encode: (array) => array.join("-"),
401 *
402 * // Take an string "1-2-3" and return an array of ints [1,2,3]
403 * decode: (str) => str.split("-").map(x => parseInt(x, 10)),
404 *
405 * // Match the encoded string in the URL
406 * pattern: new RegExp("[0-9]+(?:-[0-9]+)*")
407 *
408 * // Ensure that the (decoded) object is an array, and that all its elements are numbers
409 * is: (obj) => Array.isArray(obj) &&
410 * obj.reduce((acc, item) => acc && typeof item === 'number', true),
411 *
412 * // Compare two arrays of integers
413 * equals: (array1, array2) => array1.length === array2.length &&
414 * array1.reduce((acc, item, idx) => acc && item === array2[idx], true);
415 * });
416 *
417 * $stateProvider.state('foo', {
418 * url: "/foo/{fooIds:intarray}",
419 * onEnter: function($transition$) {
420 * console.log($transition$.fooIds); // Logs "[1, 2, 3]"
421 * }
422 * });
423 * ```
424 *
425 *
426 * This example decodes an integer from the URL.
427 * It uses the integer as an index to look up an item from a static list.
428 * That item from the list is the decoded parameter value.
429 *
430 * @example
431 * ```
432 *
433 * var list = ['John', 'Paul', 'George', 'Ringo'];
434 *
435 * $urlMatcherFactoryProvider.type('listItem', {
436 * encode: function(item) {
437 * // Represent the list item in the URL using its corresponding index
438 * return list.indexOf(item);
439 * },
440 * decode: function(item) {
441 * // Look up the list item by index
442 * return list[parseInt(item, 10)];
443 * },
444 * is: function(item) {
445 * // Ensure the item is valid by checking to see that it appears
446 * // in the list
447 * return list.indexOf(item) > -1;
448 * }
449 * });
450 *
451 * $stateProvider.state('list', {
452 * url: "/list/{item:listItem}",
453 * controller: function($scope, $stateParams) {
454 * console.log($stateParams.item);
455 * }
456 * });
457 *
458 * // ...
459 *
460 * // Changes URL to '/list/3', logs "Ringo" to the console
461 * $state.go('list', { item: "Ringo" });
462 * ```
463 *
464 * See: [[UrlConfig.type]]
465 */
466export interface ParamTypeDefinition {
467 /**
468 * A regular expression that matches the encoded parameter type
469 *
470 * This regular expression is used to match an encoded parameter value **in the URL**.
471 *
472 * For example, if your type encodes as a dash-separated numbers, match that here:
473 * `new RegExp("[0-9]+(?:-[0-9]+)*")`.
474 *
475 * There are some limitations to these regexps:
476 *
477 * - No capturing groups are allowed (use non-capturing groups: `(?: )`)
478 * - No pattern modifiers like case insensitive
479 * - No start-of-string or end-of-string: `/^foo$/`
480 */
481 pattern?: RegExp;
482 /**
483 * Disables url-encoding of parameter values
484 *
485 * If a parameter type is declared `raw`, it will not be url-encoded.
486 * Custom encoding can still be applied in the [[encode]] function.
487 *
488 * ### Decoding warning
489 *
490 * The decoding behavior of raw parameters is not defined.
491 * See: [[ParamDeclaration.raw]] for details
492 */
493 raw?: boolean;
494 /**
495 * Enables/disables inheriting of parameter values (of this type)
496 *
497 * When a transition is run with [[TransitionOptions.inherit]] set to
498 * `true`, the current param values are inherited in the new transition.
499 * However, parameters whose type has `inherit: false` set will *not be inherited*.
500 *
501 * The internal parameter type of `hash` has `inherit: false`.
502 * This is used to disable inheriting of the hash value (`#`) on subsequent transitions.
503 *
504 * #### Example:
505 * ```js
506 * $state.go('home', { '#': 'inboxAnchor' });
507 * ...
508 * // "#" is not inherited.
509 * // The value of the "#" parameter will be `null`
510 * // The url's hash will be cleared.
511 * $state.go('home.nest');
512 * ```
513 *
514 * ---
515 *
516 * See also [[TransitionOptions.inherit]] and [[ParamDeclaration.inherit]]
517 *
518 */
519 inherit?: boolean;
520 /**
521 * Dynamic flag
522 *
523 * When `dynamic` is `true`, changes to the parameter value will not cause the state to be entered/exited.
524 *
525 * Normally, if a parameter value changes, the state which declared that the parameter will be reloaded (entered/exited).
526 * When a parameter is `dynamic`, a transition still occurs, but it does not cause the state to exit/enter.
527 *
528 * Default: `false`
529 */
530 dynamic?: boolean;
531 /**
532 * Tests if some object type is compatible with this parameter type
533 *
534 * Detects whether some value is of this particular type.
535 * Accepts a decoded value and determines whether it matches this `ParamType` object.
536 *
537 * If your custom type encodes the parameter to a specific type, check for that type here.
538 * For example, if your custom type decodes the URL parameter value as an array of ints, return true if the
539 * input is an array of ints:
540 *
541 * ```
542 * is: (val) => Array.isArray(val) && array.reduce((acc, x) => acc && parseInt(val, 10) === val, true)
543 * ```
544 *
545 * If your type decodes the URL parameter value to a custom string, check that the string matches
546 * the pattern (don't use an arrow fn if you need `this`): `function (val) { return !!this.pattern.exec(val) }`
547 *
548 * Note: This method is _not used to check if the URL matches_.
549 * It's used to check if a _decoded value *is* this type_.
550 * Use [[pattern]] to check the encoded value in the URL.
551 *
552 * @param val The value to check.
553 * @param key If the type check is happening in the context of a specific [[UrlMatcher]] object,
554 * this is the name of the parameter in which `val` is stored. Can be used for
555 * meta-programming of `ParamType` objects.
556 * @returns `true` if the value matches the type, otherwise `false`.
557 */
558 is(val: any, key?: string): boolean;
559 /**
560 * Encodes a custom/native type value to a string that can be embedded in a URL.
561 *
562 * Note that the return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`).
563 * It only needs to be a representation of `val` that has been encoded as a string.
564 *
565 * For example, if your custom type decodes to an array of ints, then encode the array of ints to a string here:
566 *
567 * ```js
568 * encode: (intarray) => intarray.join("-")
569 * ```
570 *
571 * Note: in general, [[encode]] and [[decode]] should be symmetrical. That is, `encode(decode(str)) === str`
572 *
573 * @param val The value to encode.
574 * @param key The name of the parameter in which `val` is stored. Can be used for meta-programming of `ParamType` objects.
575 * @returns a string representation of `val` that can be encoded in a URL.
576 */
577 encode(val: any, key?: string): string | string[];
578 /**
579 * Decodes a parameter value string (from URL string or transition param) to a custom/native value.
580 *
581 * For example, if your type decodes to an array of ints, then decode the string as an array of ints here:
582 * ```js
583 * decode: (str) => str.split("-").map(str => parseInt(str, 10))
584 * ```
585 *
586 * Note: in general, [[encode]] and [[decode]] should be symmetrical. That is, `encode(decode(str)) === str`
587 *
588 * @param val The URL parameter value to decode.
589 * @param key The name of the parameter in which `val` is stored. Can be used for meta-programming of `ParamType` objects.
590 * @returns a custom representation of the URL parameter value.
591 */
592 decode(val: string, key?: string): any;
593 /**
594 * Determines whether two decoded values are equivalent.
595 *
596 * For example, if your type decodes to an array of ints, then check if the arrays are equal:
597 * ```js
598 * equals: (a, b) => a.length === b.length && a.reduce((acc, x, idx) => acc && x === b[idx], true)
599 * ```
600 *
601 * @param a A value to compare against.
602 * @param b A value to compare against.
603 * @returns `true` if the values are equivalent/equal, otherwise `false`.
604 */
605 equals(a: any, b: any): boolean;
606}