Skip to content

Commit 849f84f

Browse files
feat(Params): Allow inherit: false specified per parameter or type
- During a transition (which has `inherit: true`) (`StateService.go`, `uiSref`), do not inherit parameters which are declared as `{ inherit: false }` or whose type is declared as `{ inherit: false }` feat(hash): Change the hash parameter type (`'#'`) to `inherit: false` so it is cleared out when another transition occurs. Closes #3245 Closes #3218 Closes #3017
1 parent df502e8 commit 849f84f

File tree

5 files changed

+104
-13
lines changed

5 files changed

+104
-13
lines changed

src/params/param.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,13 @@ export class Param {
6767
id: string;
6868
type: ParamType;
6969
location: DefType;
70-
array: boolean;
71-
squash: (boolean|string);
72-
replace: any;
7370
isOptional: boolean;
7471
dynamic: boolean;
7572
raw: boolean;
73+
squash: (boolean|string);
74+
replace: any;
75+
inherit: boolean;
76+
array: boolean;
7677
config: any;
7778

7879
constructor(id: string, type: ParamType, config: ParamDeclaration, location: DefType, urlMatcherFactory: UrlMatcherFactory) {
@@ -85,6 +86,7 @@ export class Param {
8586
let raw = isDefined(config.raw) ? !!config.raw : !!type.raw;
8687
let squash = getSquashPolicy(config, isOptional, urlMatcherFactory.defaultSquashPolicy());
8788
let replace = getReplace(config, arrayMode, isOptional, squash);
89+
let inherit = isDefined(config.inherit) ? !!config.inherit : !!type.inherit;
8890

8991
// array config: param name (param[]) overrides default settings. explicit config overrides param name.
9092
function getArrayMode() {
@@ -93,7 +95,7 @@ export class Param {
9395
return extend(arrayDefaults, arrayParamNomenclature, config).array;
9496
}
9597

96-
extend(this, {id, type, location, squash, replace, isOptional, dynamic, raw, config, array: arrayMode});
98+
extend(this, {id, type, location, isOptional, dynamic, raw, squash, replace, inherit, array: arrayMode, config, });
9799
}
98100

99101
isDefaultValue(value: any): boolean {

src/params/paramType.ts

+7
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@ import {ParamTypeDefinition} from "./interface";
2828
* @internalapi
2929
*/
3030
export class ParamType implements ParamTypeDefinition {
31+
/** @inheritdoc */
3132
pattern: RegExp = /.*/;
33+
/** The name/id of the parameter type */
3234
name: string;
35+
/** @inheritdoc */
3336
raw: boolean;
37+
/** @inheritdoc */
3438
dynamic: boolean;
39+
/** @inheritdoc */
40+
inherit = true;
3541

3642
/**
3743
* @param def A configuration object which contains the custom type definition. The object's
@@ -136,6 +142,7 @@ function ArrayType(type: ParamType, mode: (boolean|"auto")) {
136142
dynamic: type.dynamic,
137143
name: type.name,
138144
pattern: type.pattern,
145+
inherit: type.inherit,
139146
is: arrayHandler(type.is.bind(type), true),
140147
$arrayMode: mode
141148
});

src/params/paramTypes.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -261,14 +261,16 @@ function initDefaultTypes() {
261261

262262
// Default Parameter Type Definitions
263263
extend(ParamTypes.prototype, {
264-
hash: makeDefaultType({}),
265-
266-
query: makeDefaultType({}),
267-
268264
string: makeDefaultType({}),
269265

270266
path: makeDefaultType({
271-
pattern: /[^/]*/
267+
pattern: /[^/]*/,
268+
}),
269+
270+
query: makeDefaultType({}),
271+
272+
hash: makeDefaultType({
273+
inherit: false,
272274
}),
273275

274276
int: makeDefaultType({

src/path/pathFactory.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ export class PathFactory {
7272
return extend({}, node && node.paramValues);
7373
}
7474

75+
let noInherit = fromPath.map(node => node.paramSchema)
76+
.reduce(unnestR, [])
77+
.filter(param => !param.inherit)
78+
.map(prop('id'));
79+
7580
/**
7681
* Given an [[PathNode]] "toNode", return a new [[PathNode]] with param values inherited from the
7782
* matching node in fromPath. Only inherit keys that aren't found in "toKeys" from the node in "fromPath""
@@ -82,7 +87,7 @@ export class PathFactory {
8287
// limited to only those keys found in toParams
8388
let incomingParamVals = pick(toParamVals, toKeys);
8489
toParamVals = omit(toParamVals, toKeys);
85-
let fromParamVals = nodeParamVals(fromPath, toNode.state) || {};
90+
let fromParamVals = omit(nodeParamVals(fromPath, toNode.state) || {}, noInherit);
8691
// extend toParamVals with any fromParamVals, then override any of those those with incomingParamVals
8792
let ownParamVals: RawParams = extend(toParamVals, fromParamVals, incomingParamVals);
8893
return new PathNode(toNode.state).applyRawParams(ownParamVals);

test/transitionSpec.ts

+78-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
} from "../src/index";
55
import { tree2Array, PromiseResult } from "./_testUtils";
66
import { TestingPlugin } from "./_testingPlugin";
7+
import { equals } from "../src/common/common";
78

89
describe('transition', function () {
910

@@ -783,8 +784,82 @@ describe('transition', function () {
783784
}));
784785
});
785786
});
786-
});
787787

788-
describe("initial url redirect", () => {
788+
describe('inherited params', () => {
789+
it('should inherit params when trans options `inherit: true`', async(done) => {
790+
router.stateRegistry.register({ name: 'foo', url: '/:path?query1&query2' });
791+
792+
await $state.go('foo', { path: 'abc', query1: 'def', query2: 'ghi' });
793+
expect(router.globals.params).toEqualValues({ path: 'abc', query1: 'def', query2: 'ghi' });
794+
795+
await $state.go('foo', { query2: 'jkl' });
796+
expect(router.globals.params).toEqualValues({ path: 'abc', query1: 'def', query2: 'jkl' });
797+
798+
done();
799+
});
800+
801+
it('should not inherit params when param declaration has inherit: false', async(done) => {
802+
router.stateRegistry.register({
803+
name: 'foo',
804+
url: '/:path?query1&query2',
805+
params: {
806+
query1: { inherit: false, value: null }
807+
}
808+
});
809+
810+
await $state.go('foo', { path: 'abc', query1: 'def', query2: 'ghi' });
811+
expect(router.globals.params).toEqualValues({ path: 'abc', query1: 'def', query2: 'ghi' });
812+
813+
await $state.go('foo', { query2: 'jkl' });
814+
expect(router.globals.params).toEqualValues({ path: 'abc', query1: null, query2: 'jkl' });
815+
816+
done();
817+
});
818+
819+
it('should not inherit params whose type has inherit: false', async(done) => {
820+
router.urlService.config.type('inherit', {
821+
inherit: true, encode: x=>x, decode: x=>x, is: () => true, equals: equals, pattern: /.*/, raw: false,
822+
});
823+
824+
router.urlService.config.type('noinherit', {
825+
inherit: false, encode: x=>x, decode: x=>x, is: () => true, equals: equals, pattern: /.*/, raw: false,
826+
});
827+
828+
router.stateRegistry.register({
829+
name: 'foo',
830+
url: '/?{query1:inherit}&{query2:noinherit}',
831+
});
832+
833+
await $state.go('foo', { query1: 'abc', query2: 'def' });
834+
expect(router.globals.params).toEqualValues({ query1: 'abc', query2: 'def' });
835+
836+
await $state.go('foo');
837+
expect(router.globals.params).toEqualValues({ query1: 'abc', query2: undefined });
838+
839+
done();
840+
});
841+
842+
it('should not inherit the "hash" param value', async(done) => {
843+
router.stateRegistry.register({ name: 'hash', url: '/hash' });
844+
router.stateRegistry.register({ name: 'other', url: '/other' });
789845

790-
});
846+
await $state.go('hash', { "#": "abc" });
847+
expect(router.globals.params).toEqualValues({ "#": "abc" });
848+
expect(router.urlService.hash()).toBe('abc');
849+
850+
await $state.go('hash');
851+
expect(router.globals.params).toEqualValues({ "#": null });
852+
expect(router.urlService.hash()).toBe('');
853+
854+
await $state.go('other', { "#": "def" });
855+
expect(router.globals.params).toEqualValues({ "#": "def" });
856+
expect(router.urlService.hash()).toBe('def');
857+
858+
await $state.go('hash');
859+
expect(router.globals.params).toEqualValues({ "#": null });
860+
expect(router.urlService.hash()).toBe('');
861+
862+
done();
863+
});
864+
});
865+
});

0 commit comments

Comments
 (0)