@@ -37,6 +37,7 @@ import { UIInjector } from '../interface';
3737import { RawParams } from '../params/interface' ;
3838import { ResolvableLiteral } from '../resolve/interface' ;
3939import { Rejection } from './rejectFactory' ;
40+ import { applyPairs , flattenR , uniqR } from '../common' ;
4041
4142/** @hidden */
4243const stateSelf : ( _state : StateObject ) => StateDeclaration = prop ( 'self' ) ;
@@ -286,6 +287,87 @@ export class Transition implements IHookRegistry {
286287 return Object . freeze ( this . _treeChanges [ pathname ] . map ( prop ( 'paramValues' ) ) . reduce ( mergeR , { } ) ) ;
287288 }
288289
290+ /**
291+ * Gets the new values of any parameters that changed during this transition.
292+ *
293+ * Returns any parameter values that have changed during a transition, as key/value pairs.
294+ *
295+ * - Any parameter values that have changed will be present on the returned object reflecting the new value.
296+ * - Any parameters that *not* have changed will not be present on the returned object.
297+ * - Any new parameters that weren't present in the "from" state, but are now present in the "to" state will be present on the returned object.
298+ * - Any previous parameters that are no longer present (because the "to" state doesn't have them) will be included with a value of `undefined`.
299+ *
300+ * The returned object is immutable.
301+ *
302+ * #### Examples:
303+ *
304+ * Given:
305+ * ```js
306+ * var stateA = { name: 'stateA', url: '/stateA/:param1/param2' }
307+ * var stateB = { name: 'stateB', url: '/stateB/:param3' }
308+ * var stateC = { name: 'stateB.nest', url: '/nest/:param4' }
309+ * ```
310+ *
311+ * #### Example 1
312+ *
313+ * From `/stateA/abc/def` to `/stateA/abc/xyz`
314+ *
315+ * ```js
316+ * var changed = transition.paramsChanged()
317+ * // changed is { param2: 'xyz' }
318+ * ```
319+ *
320+ * The value of `param2` changed to `xyz`.
321+ * The value of `param1` stayed the same so its value is not present.
322+ *
323+ * #### Example 2
324+ *
325+ * From `/stateA/abc/def` to `/stateB/123`
326+ *
327+ * ```js
328+ * var changed = transition.paramsChanged()
329+ * // changed is { param1: undefined, param2: undefined, param3: '123' }
330+ * ```
331+ *
332+ * The value `param3` is present because it is a new param.
333+ * Both `param1` and `param2` are no longer present so their value is undefined.
334+ *
335+ * #### Example 3
336+ *
337+ * From `/stateB/123` to `/stateB/123/nest/456`
338+ *
339+ * ```js
340+ * var changed = transition.paramsChanged()
341+ * // changed is { param4: '456' }
342+ * ```
343+ *
344+ * The value `param4` is present because it is a new param.
345+ * The value of `param3` did not change, so its value is not present.
346+ *
347+ * @returns an immutable object with changed parameter keys/values.
348+ */
349+ paramsChanged ( ) : { [ paramName : string ] : any } ;
350+ paramsChanged < T > ( ) : T ;
351+ paramsChanged ( ) {
352+ const fromParams = this . params ( 'from' ) ;
353+ const toParams = this . params ( 'to' ) ;
354+
355+ // All the parameters declared on both the "to" and "from" paths
356+ const allParamDescriptors : Param [ ] = [ ]
357+ . concat ( this . _treeChanges . to )
358+ . concat ( this . _treeChanges . from )
359+ . map ( pathNode => pathNode . paramSchema )
360+ . reduce ( flattenR , [ ] )
361+ . reduce ( uniqR , [ ] ) ;
362+
363+ const changedParamDescriptors = Param . changed ( allParamDescriptors , fromParams , toParams ) ;
364+
365+ return changedParamDescriptors . reduce ( ( changedValues , descriptor ) => {
366+ changedValues [ descriptor . id ] = toParams [ descriptor . id ] ;
367+ return changedValues ;
368+ } , { } ) ;
369+ }
370+
289371 /**
290372 * Creates a [[UIInjector]] Dependency Injector
291373 *
0 commit comments