Skip to content

Commit beca1f5

Browse files
fix(StateQueueManager): Compare parsed url parameters using typed parameters
- Removed `equalForKeys` feat(State): add .parameters() option for filtering to matching keys
1 parent b1a5155 commit beca1f5

File tree

4 files changed

+15
-25
lines changed

4 files changed

+15
-25
lines changed

src/common/common.ts

-17
Original file line numberDiff line numberDiff line change
@@ -179,23 +179,6 @@ export function ancestors(first: State, second: State) {
179179
return path;
180180
}
181181

182-
/**
183-
* Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
184-
*
185-
* @param {Object} a The first object.
186-
* @param {Object} b The second object.
187-
* @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
188-
* it defaults to the list of keys in `a`.
189-
* @return {Boolean} Returns `true` if the keys match, otherwise `false`.
190-
*/
191-
export function equalForKeys(a: Obj, b: Obj, keys: string[] = Object.keys(a)) {
192-
for (var i = 0; i < keys.length; i++) {
193-
let k = keys[i];
194-
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
195-
}
196-
return true;
197-
}
198-
199182
type PickOmitPredicate = (keys: string[], key: string) => boolean;
200183
function pickOmitImpl(predicate: PickOmitPredicate, obj: Obj, ...keys: string[]) {
201184
let objCopy = {};

src/state/stateObject.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,15 @@ export class State {
140140
*
141141
* Gets [[Param]] information that is owned by the state.
142142
* If `opts.inherit` is true, it also includes the ancestor states' [[Param]] information.
143+
* If `opts.matchingKeys` exists, returns only `Param`s whose `id` is a key on the `matchingKeys` object
143144
*
144145
* @param opts options
145146
*/
146-
parameters(opts?: { inherit?: boolean }): Param[] {
147-
opts = defaults(opts, { inherit: true });
147+
parameters(opts?: { inherit?: boolean, matchingKeys?: any }): Param[] {
148+
opts = defaults(opts, { inherit: true, matchingKeys: null });
148149
let inherited = opts.inherit && this.parent && this.parent.parameters() || [];
149-
return inherited.concat(values(this.params));
150+
return inherited.concat(values(this.params))
151+
.filter(param => !opts.matchingKeys || opts.matchingKeys.hasOwnProperty(param.id));
150152
}
151153

152154
/**

src/state/stateQueueManager.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** @module state */ /** for typedoc */
2-
import {extend, inherit, pluck, equalForKeys} from "../common/common";
2+
import {extend, inherit, pluck} from "../common/common";
33
import {isString} from "../common/predicates";
44
import {StateDeclaration} from "./interface";
55
import {State} from "./stateObject";
@@ -8,6 +8,7 @@ import {StateService} from "./stateService";
88
import {UrlRouterProvider} from "../url/urlRouter";
99
import {RawParams} from "../params/interface";
1010
import {StateRegistry, StateRegistryListener} from "./stateRegistry";
11+
import { Param } from "../params/param";
1112

1213
export class StateQueueManager {
1314
queue: State[];
@@ -105,7 +106,12 @@ export class StateQueueManager {
105106
if (state.abstract || !state.url) return;
106107

107108
$urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match: RawParams, $stateParams: RawParams) {
108-
if ($state.$current.navigable !== state || !equalForKeys($match, $stateParams)) {
109+
function matchedParamsEqual() {
110+
let schema: Param[] = state.parameters({ inherit: true, matchingKeys: $match });
111+
return Param.equals(schema, Param.values(schema, $match), $stateParams);
112+
}
113+
114+
if ($state.$current.navigable !== state || !matchedParamsEqual()) {
109115
$state.transitionTo(state, $match, { inherit: true, source: "url" });
110116
}
111117
}], (rule) => state._urlRule = rule);

src/state/stateService.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {RawParams} from "../params/interface";
2020
import {ParamsOrArray} from "../params/interface";
2121
import {Param} from "../params/param";
2222
import {Glob} from "../common/glob";
23-
import {equalForKeys} from "../common/common";
2423
import {HrefOptions} from "./interface";
2524
import {bindFunctions} from "../common/common";
2625
import {Globals} from "../globals";
@@ -412,7 +411,7 @@ export class StateService {
412411
if (this.$current !== state) return false;
413412
if (!params) return true;
414413

415-
let schema: Param[] = state.parameters({ inherit: true }).filter(param => params.hasOwnProperty(param.id));
414+
let schema: Param[] = state.parameters({ inherit: true, matchingKeys: params });
416415
return Param.equals(schema, Param.values(schema, params), this.params);
417416
};
418417

@@ -468,7 +467,7 @@ export class StateService {
468467
if (!isDefined(include[state.name])) return false;
469468
if (!params) return true;
470469

471-
let schema: Param[] = state.parameters({ inherit: true }).filter(param => params.hasOwnProperty(param.id));
470+
let schema: Param[] = state.parameters({ inherit: true, matchingKeys: params });
472471
return Param.equals(schema, Param.values(schema, params), this.params);
473472
};
474473

0 commit comments

Comments
 (0)