Skip to content

Commit

Permalink
feat(Params): Allow inherit: false specified per parameter or type
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
christopherthielen committed Jan 7, 2017
1 parent df502e8 commit 849f84f
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 13 deletions.
10 changes: 6 additions & 4 deletions src/params/param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ export class Param {
id: string;
type: ParamType;
location: DefType;
array: boolean;
squash: (boolean|string);
replace: any;
isOptional: boolean;
dynamic: boolean;
raw: boolean;
squash: (boolean|string);
replace: any;
inherit: boolean;
array: boolean;
config: any;

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

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

extend(this, {id, type, location, squash, replace, isOptional, dynamic, raw, config, array: arrayMode});
extend(this, {id, type, location, isOptional, dynamic, raw, squash, replace, inherit, array: arrayMode, config, });
}

isDefaultValue(value: any): boolean {
Expand Down
7 changes: 7 additions & 0 deletions src/params/paramType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ import {ParamTypeDefinition} from "./interface";
* @internalapi
*/
export class ParamType implements ParamTypeDefinition {
/** @inheritdoc */
pattern: RegExp = /.*/;
/** The name/id of the parameter type */
name: string;
/** @inheritdoc */
raw: boolean;
/** @inheritdoc */
dynamic: boolean;
/** @inheritdoc */
inherit = true;

/**
* @param def A configuration object which contains the custom type definition. The object's
Expand Down Expand Up @@ -136,6 +142,7 @@ function ArrayType(type: ParamType, mode: (boolean|"auto")) {
dynamic: type.dynamic,
name: type.name,
pattern: type.pattern,
inherit: type.inherit,
is: arrayHandler(type.is.bind(type), true),
$arrayMode: mode
});
Expand Down
12 changes: 7 additions & 5 deletions src/params/paramTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,16 @@ function initDefaultTypes() {

// Default Parameter Type Definitions
extend(ParamTypes.prototype, {
hash: makeDefaultType({}),

query: makeDefaultType({}),

string: makeDefaultType({}),

path: makeDefaultType({
pattern: /[^/]*/
pattern: /[^/]*/,
}),

query: makeDefaultType({}),

hash: makeDefaultType({
inherit: false,
}),

int: makeDefaultType({
Expand Down
7 changes: 6 additions & 1 deletion src/path/pathFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export class PathFactory {
return extend({}, node && node.paramValues);
}

let noInherit = fromPath.map(node => node.paramSchema)
.reduce(unnestR, [])
.filter(param => !param.inherit)
.map(prop('id'));

/**
* Given an [[PathNode]] "toNode", return a new [[PathNode]] with param values inherited from the
* matching node in fromPath. Only inherit keys that aren't found in "toKeys" from the node in "fromPath""
Expand All @@ -82,7 +87,7 @@ export class PathFactory {
// limited to only those keys found in toParams
let incomingParamVals = pick(toParamVals, toKeys);
toParamVals = omit(toParamVals, toKeys);
let fromParamVals = nodeParamVals(fromPath, toNode.state) || {};
let fromParamVals = omit(nodeParamVals(fromPath, toNode.state) || {}, noInherit);
// extend toParamVals with any fromParamVals, then override any of those those with incomingParamVals
let ownParamVals: RawParams = extend(toParamVals, fromParamVals, incomingParamVals);
return new PathNode(toNode.state).applyRawParams(ownParamVals);
Expand Down
81 changes: 78 additions & 3 deletions test/transitionSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from "../src/index";
import { tree2Array, PromiseResult } from "./_testUtils";
import { TestingPlugin } from "./_testingPlugin";
import { equals } from "../src/common/common";

describe('transition', function () {

Expand Down Expand Up @@ -783,8 +784,82 @@ describe('transition', function () {
}));
});
});
});

describe("initial url redirect", () => {
describe('inherited params', () => {
it('should inherit params when trans options `inherit: true`', async(done) => {
router.stateRegistry.register({ name: 'foo', url: '/:path?query1&query2' });

await $state.go('foo', { path: 'abc', query1: 'def', query2: 'ghi' });
expect(router.globals.params).toEqualValues({ path: 'abc', query1: 'def', query2: 'ghi' });

await $state.go('foo', { query2: 'jkl' });
expect(router.globals.params).toEqualValues({ path: 'abc', query1: 'def', query2: 'jkl' });

done();
});

it('should not inherit params when param declaration has inherit: false', async(done) => {
router.stateRegistry.register({
name: 'foo',
url: '/:path?query1&query2',
params: {
query1: { inherit: false, value: null }
}
});

await $state.go('foo', { path: 'abc', query1: 'def', query2: 'ghi' });
expect(router.globals.params).toEqualValues({ path: 'abc', query1: 'def', query2: 'ghi' });

await $state.go('foo', { query2: 'jkl' });
expect(router.globals.params).toEqualValues({ path: 'abc', query1: null, query2: 'jkl' });

done();
});

it('should not inherit params whose type has inherit: false', async(done) => {
router.urlService.config.type('inherit', {
inherit: true, encode: x=>x, decode: x=>x, is: () => true, equals: equals, pattern: /.*/, raw: false,
});

router.urlService.config.type('noinherit', {
inherit: false, encode: x=>x, decode: x=>x, is: () => true, equals: equals, pattern: /.*/, raw: false,
});

router.stateRegistry.register({
name: 'foo',
url: '/?{query1:inherit}&{query2:noinherit}',
});

await $state.go('foo', { query1: 'abc', query2: 'def' });
expect(router.globals.params).toEqualValues({ query1: 'abc', query2: 'def' });

await $state.go('foo');
expect(router.globals.params).toEqualValues({ query1: 'abc', query2: undefined });

done();
});

it('should not inherit the "hash" param value', async(done) => {
router.stateRegistry.register({ name: 'hash', url: '/hash' });
router.stateRegistry.register({ name: 'other', url: '/other' });

});
await $state.go('hash', { "#": "abc" });
expect(router.globals.params).toEqualValues({ "#": "abc" });
expect(router.urlService.hash()).toBe('abc');

await $state.go('hash');
expect(router.globals.params).toEqualValues({ "#": null });
expect(router.urlService.hash()).toBe('');

await $state.go('other', { "#": "def" });
expect(router.globals.params).toEqualValues({ "#": "def" });
expect(router.urlService.hash()).toBe('def');

await $state.go('hash');
expect(router.globals.params).toEqualValues({ "#": null });
expect(router.urlService.hash()).toBe('');

done();
});
});
});

0 comments on commit 849f84f

Please sign in to comment.