Skip to content

Commit 76bc2ba

Browse files
committed
Allow handing in numbers (indices) to path composition
1 parent 416654a commit 76bc2ba

File tree

14 files changed

+34
-23
lines changed

14 files changed

+34
-23
lines changed

MIGRATION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const CustomRenderer = (props: ControlProps & WithInput) => {
9595
// Dispatch needs the path from the root of JSON Forms's data
9696
// Thus, calculate it by extending this control's path
9797
const dispatchEntries = arrayData.map((arrayEntry, index) => {
98-
const entryPath = Paths.compose(path, 'array~Data', `${index}`);
98+
const entryPath = Paths.compose(path, 'array~Data', index);
9999
const schema = Resolve.schema();
100100
return (
101101
<JsonFormsDispatch

packages/angular-material/src/library/layouts/array-layout.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ export class ArrayLayoutRenderer
233233
}
234234
return {
235235
schema: this.scopedSchema,
236-
path: Paths.compose(this.propsPath, `${index}`),
236+
path: Paths.compose(this.propsPath, index),
237237
uischema,
238238
};
239239
}

packages/angular-material/src/library/other/master-detail/master.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export class MasterListComponent
225225
? d.toString()
226226
: get(d, labelRefInstancePath ?? getFirstPrimitiveProp(schema)),
227227
data: d,
228-
path: Paths.compose(path, `${index}`),
228+
path: Paths.compose(path, index),
229229
schema,
230230
uischema: detailUISchema,
231231
};

packages/angular-material/src/library/other/table.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ export const controlWithoutLabel = (scope: string): ControlElement => ({
273273
@Pipe({ name: 'getProps' })
274274
export class GetProps implements PipeTransform {
275275
transform(index: number, props: OwnPropsOfRenderer) {
276-
const rowPath = Paths.compose(props.path, `${index}`);
276+
const rowPath = Paths.compose(props.path, index);
277277
return {
278278
schema: props.schema,
279279
uischema: props.uischema,

packages/core/src/mappers/renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ export const mapStateToMasterListItemProps = (
717717
ownProps: OwnPropsOfMasterListItem
718718
): StatePropsOfMasterItem => {
719719
const { schema, path, uischema, childLabelProp, index } = ownProps;
720-
const childPath = composePaths(path, `${index}`);
720+
const childPath = composePaths(path, index);
721721
const childLabel = computeChildLabel(
722722
getData(state),
723723
childPath,

packages/core/src/util/path.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,24 @@ import range from 'lodash/range';
3939
* The segments are appended in order to the JSON pointer and the special characters `~` and `/` are automatically encoded.
4040
*
4141
* @param {string} pointer Initial valid JSON pointer
42-
* @param {...string[]} segments **unencoded** path segments to append to the JSON pointer
42+
* @param {...(string | number)[]} segments **unencoded** path segments to append to the JSON pointer. May also be a number in case of indices.
4343
* @returns {string} resulting JSON pointer
4444
*/
45-
export const compose = (pointer: string, ...segments: string[]): string => {
46-
return segments.reduce((currentPointer, segment) => {
47-
// Only skip undefined segments, as empty string segments are allowed
48-
// and reference a property that has the empty string as property name.
49-
if (segment === undefined) {
50-
return currentPointer;
51-
}
52-
return `${currentPointer}/${encode(segment)}`;
53-
}, pointer ?? '');
45+
export const compose = (
46+
pointer: string,
47+
...segments: (string | number)[]
48+
): string => {
49+
// Remove undefined segments and encode string segments. Number don't need encoding.
50+
// Only skip undefined segments, as empty string segments are allowed
51+
// and reference a property that has the empty string as property name.
52+
const sanitizedSegments = segments
53+
.filter((s) => s !== undefined)
54+
.map((s) => (typeof s === 'string' ? encode(s) : s.toString()));
55+
56+
return sanitizedSegments.reduce(
57+
(currentPointer, segment) => `${currentPointer}/${segment}`,
58+
pointer ?? ''
59+
);
5460
};
5561

5662
export { compose as composePaths };

packages/core/test/util/path.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ test('compose - handles root json pointer', (t) => {
304304
t.is(result, '/foo');
305305
});
306306

307+
test('compose - handles numbers', (t) => {
308+
const result = compose('/foo', 0, 'bar');
309+
t.is(result, '/foo/0/bar');
310+
});
311+
307312
/*
308313
* Unexpected edge case but the RFC6901 standard defines that `/` points to a property with key `''`.
309314
* To point to the root object, the empty string `''` is used.

packages/material-renderers/src/complex/MaterialEnumArrayRenderer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const MaterialEnumArrayRenderer = ({
8080
</FormLabel>
8181
<FormGroup row>
8282
{options.map((option: any, index: number) => {
83-
const optionPath = Paths.compose(path, `${index}`);
83+
const optionPath = Paths.compose(path, index);
8484
const checkboxValue = data?.includes(option.value)
8585
? option.value
8686
: undefined;

packages/material-renderers/src/complex/MaterialTableControl.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ const TableRows = ({
422422
return (
423423
<React.Fragment>
424424
{range(data).map((index: number) => {
425-
const childPath = Paths.compose(path, `${index}`);
425+
const childPath = Paths.compose(path, index);
426426

427427
return (
428428
<NonEmptyRow

packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ export const withContextToExpandPanelProps = (
357357
// eslint-disable-next-line react/prop-types
358358
uischemas,
359359
} = props;
360-
const childPath = composePaths(path, `${index}`);
360+
const childPath = composePaths(path, index);
361361

362362
const childLabel = useMemo(() => {
363363
return computeChildLabel(

0 commit comments

Comments
 (0)