diff --git a/src/common/common.ts b/src/common/common.ts index 1357c7c7..5fac6621 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -179,23 +179,6 @@ export function ancestors(first: State, second: State) { return path; } -/** - * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. - * - * @param {Object} a The first object. - * @param {Object} b The second object. - * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, - * it defaults to the list of keys in `a`. - * @return {Boolean} Returns `true` if the keys match, otherwise `false`. - */ -export function equalForKeys(a: Obj, b: Obj, keys: string[] = Object.keys(a)) { - for (var i = 0; i < keys.length; i++) { - let k = keys[i]; - if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized - } - return true; -} - type PickOmitPredicate = (keys: string[], key: string) => boolean; function pickOmitImpl(predicate: PickOmitPredicate, obj: Obj, ...keys: string[]) { let objCopy = {}; diff --git a/src/state/stateObject.ts b/src/state/stateObject.ts index 7ff5cc9c..9b70d4df 100644 --- a/src/state/stateObject.ts +++ b/src/state/stateObject.ts @@ -140,13 +140,15 @@ export class State { * * Gets [[Param]] information that is owned by the state. * If `opts.inherit` is true, it also includes the ancestor states' [[Param]] information. + * If `opts.matchingKeys` exists, returns only `Param`s whose `id` is a key on the `matchingKeys` object * * @param opts options */ - parameters(opts?: { inherit?: boolean }): Param[] { - opts = defaults(opts, { inherit: true }); + parameters(opts?: { inherit?: boolean, matchingKeys?: any }): Param[] { + opts = defaults(opts, { inherit: true, matchingKeys: null }); let inherited = opts.inherit && this.parent && this.parent.parameters() || []; - return inherited.concat(values(this.params)); + return inherited.concat(values(this.params)) + .filter(param => !opts.matchingKeys || opts.matchingKeys.hasOwnProperty(param.id)); } /** diff --git a/src/state/stateQueueManager.ts b/src/state/stateQueueManager.ts index 2c4b8615..cae49edb 100644 --- a/src/state/stateQueueManager.ts +++ b/src/state/stateQueueManager.ts @@ -1,5 +1,5 @@ /** @module state */ /** for typedoc */ -import {extend, inherit, pluck, equalForKeys} from "../common/common"; +import {extend, inherit, pluck} from "../common/common"; import {isString} from "../common/predicates"; import {StateDeclaration} from "./interface"; import {State} from "./stateObject"; @@ -8,6 +8,7 @@ import {StateService} from "./stateService"; import {UrlRouterProvider} from "../url/urlRouter"; import {RawParams} from "../params/interface"; import {StateRegistry, StateRegistryListener} from "./stateRegistry"; +import { Param } from "../params/param"; export class StateQueueManager { queue: State[]; @@ -105,7 +106,12 @@ export class StateQueueManager { if (state.abstract || !state.url) return; $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match: RawParams, $stateParams: RawParams) { - if ($state.$current.navigable !== state || !equalForKeys($match, $stateParams)) { + function matchedParamsEqual() { + let schema: Param[] = state.parameters({ inherit: true, matchingKeys: $match }); + return Param.equals(schema, Param.values(schema, $match), $stateParams); + } + + if ($state.$current.navigable !== state || !matchedParamsEqual()) { $state.transitionTo(state, $match, { inherit: true, source: "url" }); } }], (rule) => state._urlRule = rule); diff --git a/src/state/stateService.ts b/src/state/stateService.ts index 2f840569..a8fa292b 100644 --- a/src/state/stateService.ts +++ b/src/state/stateService.ts @@ -20,7 +20,6 @@ import {RawParams} from "../params/interface"; import {ParamsOrArray} from "../params/interface"; import {Param} from "../params/param"; import {Glob} from "../common/glob"; -import {equalForKeys} from "../common/common"; import {HrefOptions} from "./interface"; import {bindFunctions} from "../common/common"; import {Globals} from "../globals"; @@ -412,7 +411,7 @@ export class StateService { if (this.$current !== state) return false; if (!params) return true; - let schema: Param[] = state.parameters({ inherit: true }).filter(param => params.hasOwnProperty(param.id)); + let schema: Param[] = state.parameters({ inherit: true, matchingKeys: params }); return Param.equals(schema, Param.values(schema, params), this.params); }; @@ -468,7 +467,7 @@ export class StateService { if (!isDefined(include[state.name])) return false; if (!params) return true; - let schema: Param[] = state.parameters({ inherit: true }).filter(param => params.hasOwnProperty(param.id)); + let schema: Param[] = state.parameters({ inherit: true, matchingKeys: params }); return Param.equals(schema, Param.values(schema, params), this.params); };