Skip to content

Commit 323418f

Browse files
committed
Allow handing in numbers (indices) to path composition
1 parent 0fb28ca commit 323418f

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/util/path.ts

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

5763
export { compose as composePaths };

packages/core/src/util/renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ export const mapStateToMasterListItemProps = (
689689
ownProps: OwnPropsOfMasterListItem
690690
): StatePropsOfMasterItem => {
691691
const { schema, path, uischema, childLabelProp, index } = ownProps;
692-
const childPath = composePaths(path, `${index}`);
692+
const childPath = composePaths(path, index);
693693
const childLabel = computeChildLabel(
694694
getData(state),
695695
childPath,

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
@@ -424,7 +424,7 @@ const TableRows = ({
424424
return (
425425
<React.Fragment>
426426
{range(data).map((index: number) => {
427-
const childPath = Paths.compose(path, `${index}`);
427+
const childPath = Paths.compose(path, index);
428428

429429
return (
430430
<NonEmptyRow

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

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

364364
const childLabel = useMemo(() => {
365365
return computeChildLabel(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const MaterialArrayLayoutComponent = (props: ArrayLayoutProps) => {
4848
[]
4949
);
5050
const isExpanded = (index: number) =>
51-
expanded === composePaths(props.path, `${index}`);
51+
expanded === composePaths(props.path, index);
5252

5353
const {
5454
enabled,

packages/vanilla-renderers/src/complex/TableArrayControl.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class TableArrayControl extends React.Component<
146146
</tr>
147147
) : (
148148
data.map((_child, index) => {
149-
const childPath = Paths.compose(path, `${index}`);
149+
const childPath = Paths.compose(path, index);
150150
const errorsPerEntry: any[] = filter(childErrors, (error) => {
151151
const errorPath = getControlPath(error);
152152
return errorPath.startsWith(childPath);
@@ -189,7 +189,7 @@ class TableArrayControl extends React.Component<
189189
})
190190
)(schema.properties)
191191
) : (
192-
<td key={Paths.compose(childPath, `${index}`)}>
192+
<td key={Paths.compose(childPath, index)}>
193193
<DispatchCell
194194
schema={schema}
195195
uischema={createControlElement()}

packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const ArrayControl = ({
107107
<div className={classNames.children}>
108108
{data ? (
109109
range(0, data.length).map((index) => {
110-
const childPath = composePaths(path, `${index}`);
110+
const childPath = composePaths(path, index);
111111
return (
112112
<div key={index}>
113113
<JsonFormsDispatch

packages/vue-vanilla/src/array/ArrayListRenderer.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<dispatch-renderer
3434
:schema="control.schema"
3535
:uischema="childUiSchema"
36-
:path="composePaths(control.path, `${index}`)"
36+
:path="composePaths(control.path, index)"
3737
:enabled="control.enabled"
3838
:renderers="control.renderers"
3939
:cells="control.cells"

0 commit comments

Comments
 (0)