Skip to content

Commit

Permalink
fix(StateQueueManager): Compare parsed url parameters using typed par…
Browse files Browse the repository at this point in the history
…ameters

- Removed `equalForKeys`

feat(State): add .parameters() option for filtering to matching keys
  • Loading branch information
christopherthielen committed Nov 30, 2016
1 parent b1a5155 commit beca1f5
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 25 deletions.
17 changes: 0 additions & 17 deletions src/common/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};
Expand Down
8 changes: 5 additions & 3 deletions src/state/stateObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/**
Expand Down
10 changes: 8 additions & 2 deletions src/state/stateQueueManager.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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[];
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions src/state/stateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
};

Expand Down Expand Up @@ -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);
};

Expand Down

0 comments on commit beca1f5

Please sign in to comment.