From 8f951602f1ee089262533e464d9a0dd01dbbe086 Mon Sep 17 00:00:00 2001 From: Alexandra Buzila Date: Thu, 9 Nov 2023 14:44:22 +0100 Subject: [PATCH] feat: respect "default" values when creating new elements in an array Initialize new array elements with their default values. Fixes default value returned for string schemas with a date format. Fixes #2195 Contributed on behalf of STMicroelectronics Signed-off-by: Alexandra Buzila --- .../src/layouts/array-layout.renderer.ts | 5 +- .../src/other/master-detail/master.ts | 5 +- .../src/other/table.renderer.ts | 5 +- packages/core/src/util/renderer.ts | 79 +++++--- packages/core/src/util/util.ts | 43 ++++ packages/core/test/util/renderer.test.ts | 183 +++++++++++++++--- .../src/examples/arrays-with-defaults.ts | 129 ++++++++++++ packages/examples/src/index.ts | 2 + .../MaterialListWithDetailRenderer.tsx | 2 +- .../src/complex/MaterialAnyOfRenderer.tsx | 10 +- .../src/complex/MaterialOneOfRenderer.tsx | 5 +- .../src/complex/TableToolbar.tsx | 3 +- .../src/layouts/MaterialArrayLayout.tsx | 2 +- .../src/complex/TableArrayControl.tsx | 2 +- .../complex/array/ArrayControlRenderer.tsx | 2 +- .../src/array/ArrayListRenderer.vue | 2 +- .../vue-vanilla/src/complex/OneOfRenderer.vue | 4 +- 17 files changed, 421 insertions(+), 62 deletions(-) create mode 100644 packages/examples/src/examples/arrays-with-defaults.ts diff --git a/packages/angular-material/src/layouts/array-layout.renderer.ts b/packages/angular-material/src/layouts/array-layout.renderer.ts index eb1b3c1b6..da21164f0 100644 --- a/packages/angular-material/src/layouts/array-layout.renderer.ts +++ b/packages/angular-material/src/layouts/array-layout.renderer.ts @@ -180,7 +180,10 @@ export class ArrayLayoutRenderer this.removeItems(this.propsPath, [index])(); } add(): void { - this.addItem(this.propsPath, createDefaultValue(this.scopedSchema))(); + this.addItem( + this.propsPath, + createDefaultValue(this.scopedSchema, this.rootSchema) + )(); } up(index: number): void { this.moveItemUp(this.propsPath, index)(); diff --git a/packages/angular-material/src/other/master-detail/master.ts b/packages/angular-material/src/other/master-detail/master.ts index 8b8f58b3d..3b47935c6 100644 --- a/packages/angular-material/src/other/master-detail/master.ts +++ b/packages/angular-material/src/other/master-detail/master.ts @@ -263,7 +263,10 @@ export class MasterListComponent } onAddClick() { - this.addItem(this.propsPath, createDefaultValue(this.scopedSchema))(); + this.addItem( + this.propsPath, + createDefaultValue(this.scopedSchema, this.rootSchema) + )(); } onDeleteClick(item: number) { diff --git a/packages/angular-material/src/other/table.renderer.ts b/packages/angular-material/src/other/table.renderer.ts index 7cdcdb991..8be5d06c3 100644 --- a/packages/angular-material/src/other/table.renderer.ts +++ b/packages/angular-material/src/other/table.renderer.ts @@ -175,7 +175,10 @@ export class TableRenderer extends JsonFormsArrayControl implements OnInit { this.removeItems(this.propsPath, [index])(); } add(): void { - this.addItem(this.propsPath, createDefaultValue(this.scopedSchema))(); + this.addItem( + this.propsPath, + createDefaultValue(this.scopedSchema, this.rootSchema) + )(); } up(index: number): void { this.moveItemUp(this.propsPath, index)(); diff --git a/packages/core/src/util/renderer.ts b/packages/core/src/util/renderer.ts index 75773e472..1346efdef 100644 --- a/packages/core/src/util/renderer.ts +++ b/packages/core/src/util/renderer.ts @@ -57,7 +57,7 @@ import { createLabelDescriptionFrom } from './label'; import type { CombinatorKeyword } from './combinators'; import { moveDown, moveUp } from './array'; import type { AnyAction, Dispatch } from './type'; -import { Resolve } from './util'; +import { Resolve, convertDateToString, hasType } from './util'; import { composePaths, composeWithUi } from './path'; import { CoreActions, update } from '../actions'; import type { ErrorObject } from 'ajv'; @@ -79,6 +79,7 @@ import { ArrayTranslations, } from '../i18n/arrayTranslations'; import { resolveSchema } from './resolvers'; +import cloneDeep from 'lodash/cloneDeep'; const isRequired = ( schema: JsonSchema, @@ -138,33 +139,65 @@ export const showAsRequired = ( }; /** - * Create a default value based on the given scheam. + * Create a default value based on the given schema. * @param schema the schema for which to create a default value. * @returns {any} */ -export const createDefaultValue = (schema: JsonSchema) => { - switch (schema.type) { - case 'string': - if ( - schema.format === 'date-time' || - schema.format === 'date' || - schema.format === 'time' - ) { - return new Date(); +export const createDefaultValue = ( + schema: JsonSchema, + rootSchema: JsonSchema +) => { + const resolvedSchema = Resolve.schema(schema, schema.$ref, rootSchema); + if (resolvedSchema.default !== undefined) { + return extractDefaults(resolvedSchema, rootSchema); + } + if (hasType(resolvedSchema, 'string')) { + if ( + resolvedSchema.format === 'date-time' || + resolvedSchema.format === 'date' || + resolvedSchema.format === 'time' + ) { + return convertDateToString(new Date(), resolvedSchema.format); + } + return ''; + } else if ( + hasType(resolvedSchema, 'integer') || + hasType(resolvedSchema, 'number') + ) { + return 0; + } else if (hasType(resolvedSchema, 'boolean')) { + return false; + } else if (hasType(resolvedSchema, 'array')) { + return []; + } else if (hasType(resolvedSchema, 'object')) { + return extractDefaults(resolvedSchema, rootSchema); + } else if (hasType(resolvedSchema, 'null')) { + return null; + } else { + return {}; + } +}; + +/** + * Returns the default value defined in the given schema. + * @param schema the schema for which to create a default value. + * @returns {any} + */ +export const extractDefaults = (schema: JsonSchema, rootSchema: JsonSchema) => { + if (hasType(schema, 'object') && schema.default === undefined) { + const result: { [key: string]: any } = {}; + for (const key in schema.properties) { + const property = schema.properties[key]; + const resolvedProperty = property.$ref + ? Resolve.schema(rootSchema, property.$ref, rootSchema) + : property; + if (resolvedProperty.default !== undefined) { + result[key] = cloneDeep(resolvedProperty.default); } - return ''; - case 'integer': - case 'number': - return 0; - case 'boolean': - return false; - case 'array': - return []; - case 'null': - return null; - default: - return {}; + } + return result; } + return cloneDeep(schema.default); }; /** diff --git a/packages/core/src/util/util.ts b/packages/core/src/util/util.ts index 43a4cc6b3..ba1aabadd 100644 --- a/packages/core/src/util/util.ts +++ b/packages/core/src/util/util.ts @@ -33,6 +33,49 @@ import { composePaths, toDataPathSegments } from './path'; import { isEnabled, isVisible } from './runtime'; import type Ajv from 'ajv'; +/** + * Returns the string representation of the given date. The format of the output string can be specified: + * - 'date' for a date-only string (YYYY-MM-DD), + * - 'time' for a time-only string (HH:mm:ss), or + * - 'date-time' for a full date-time string in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ). + * If no format is specified, the full date-time ISO string is returned by default. + * + * @returns {string} A string representation of the date in the specified format. + * + * @example + * // returns '2023-11-09' + * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'date'); + * + * @example + * // returns '14:22:54' + * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'time'); + * + * @example + * // returns '2023-11-09T14:22:54.131Z' + * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'date-time'); + * + * @example + * // returns '2023-11-09T14:22:54.131Z' + * convertDateToString(new Date('2023-11-09T14:22:54.131Z')); + */ +export const convertDateToString = ( + date: Date, + format?: 'date' | 'time' | 'date-time' +): string => { + //e.g. '2023-11-09T14:22:54.131Z' + const dateString = date.toISOString(); + if (format === 'date-time') { + return dateString; + } else if (format === 'date') { + // e.g. '2023-11-09' + return dateString.split('T')[0]; + } else if (format === 'time') { + //e.g. '14:22:54' + return dateString.split('T')[1].split('.')[0]; + } + return dateString; +}; + /** * Escape the given string such that it can be used as a class name, * i.e. hashes and slashes will be replaced. diff --git a/packages/core/test/util/renderer.test.ts b/packages/core/test/util/renderer.test.ts index 1442f1040..afbebaffd 100644 --- a/packages/core/test/util/renderer.test.ts +++ b/packages/core/test/util/renderer.test.ts @@ -70,6 +70,7 @@ import { createAjv } from '../../src/util/validator'; import { JsonSchema7 } from '../../src/models/jsonSchema7'; import { defaultJsonFormsI18nState } from '../../src/reducers/i18n'; import { i18nJsonSchema } from '../../src/i18n/i18nTypes'; +import { convertDateToString } from '../../src/util'; const middlewares: Redux.Middleware[] = []; const mockStore = configureStore(middlewares); @@ -494,38 +495,170 @@ test('mapDispatchToControlProps', (t) => { }); test('createDefaultValue', (t) => { - t.true( - _.isDate( - createDefaultValue({ + t.is( + createDefaultValue( + { type: 'string', format: 'date', - }) - ) + }, + { + type: 'string', + format: 'date', + } + ), + convertDateToString(new Date(), 'date') ); - t.true( - _.isDate( - createDefaultValue({ + t.regex( + createDefaultValue( + { type: 'string', format: 'date-time', - }) - ) + }, + { + type: 'string', + format: 'date-time', + } + ), + /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/ ); - t.true( - _.isDate( - createDefaultValue({ + t.regex( + createDefaultValue( + { type: 'string', format: 'time', - }) - ) + }, + { + type: 'string', + format: 'time', + } + ), + /^\d{2}:\d{2}:\d{2}$/ + ); + t.is(createDefaultValue({ type: 'string' }, { type: 'string' }), ''); + t.is(createDefaultValue({ type: 'number' }, { type: 'number' }), 0); + t.falsy(createDefaultValue({ type: 'boolean' }, { type: 'boolean' })); + t.is(createDefaultValue({ type: 'integer' }, { type: 'integer' }), 0); + t.deepEqual(createDefaultValue({ type: 'array' }, { type: 'array' }), []); + t.is(createDefaultValue({ type: 'null' }, { type: 'null' }), null); + t.deepEqual(createDefaultValue({ type: 'object' }, { type: 'object' }), {}); + t.deepEqual( + createDefaultValue({ type: 'something' }, { type: 'something' }), + {} ); - t.is(createDefaultValue({ type: 'string' }), ''); - t.is(createDefaultValue({ type: 'number' }), 0); - t.falsy(createDefaultValue({ type: 'boolean' })); - t.is(createDefaultValue({ type: 'integer' }), 0); - t.deepEqual(createDefaultValue({ type: 'array' }), []); - t.is(createDefaultValue({ type: 'null' }), null); - t.deepEqual(createDefaultValue({ type: 'object' }), {}); - t.deepEqual(createDefaultValue({ type: 'something' }), {}); + + // defaults: + t.deepEqual( + createDefaultValue( + { + type: 'string', + default: '2023-10-10', + }, + { + type: 'string', + default: '2023-10-10', + } + ), + '2023-10-10' + ); + t.is( + createDefaultValue( + { type: 'string', default: 'excellent' }, + { type: 'string', default: 'excellent' } + ), + 'excellent' + ); + t.is( + createDefaultValue( + { type: 'number', default: 10 }, + { type: 'number', default: 10 } + ), + 10 + ); + t.is( + createDefaultValue( + { type: 'boolean', default: true }, + { type: 'boolean', default: true } + ), + true + ); + t.is( + createDefaultValue( + { type: 'integer', default: 11 }, + { type: 'integer', default: 11 } + ), + 11 + ); + t.deepEqual( + createDefaultValue( + { type: 'array', default: ['a', 'b', 'c'] }, + { type: 'array', default: ['a', 'b', 'c'] } + ), + ['a', 'b', 'c'] + ); + t.deepEqual( + createDefaultValue( + { type: 'object', default: { foo: 'bar' } }, + { type: 'object', default: { foo: 'bar' } } + ), + { + foo: 'bar', + } + ); + const objectSchema = { + type: 'object', + properties: { + string1: { type: 'string', default: 'excellent' }, + string2: { type: 'string' }, + number: { type: 'number', default: 10 }, + int: { type: 'integer', default: 11 }, + bool: { type: 'boolean', default: true }, + array: { type: 'array', default: ['a', 'b', 'c'] }, + }, + }; + t.deepEqual(createDefaultValue(objectSchema, objectSchema), { + string1: 'excellent', + number: 10, + int: 11, + bool: true, + array: ['a', 'b', 'c'], + }); + + const rootSchemaWithRefs = { + definitions: { + stringDef: { type: 'string', default: 'excellent' }, + numberDef: { type: 'number', default: 10 }, + intDef: { type: 'integer', default: 11 }, + boolDef: { type: 'boolean', default: true }, + arrayDef: { type: 'array', default: ['a', 'b', 'c'] }, + }, + type: 'object', + properties: { + string1: { $ref: '#/definitions/stringDef' }, + string2: { type: 'string' }, + number: { $ref: '#/definitions/numberDef' }, + int: { $ref: '#/definitions/intDef' }, + bool: { $ref: '#/definitions/boolDef' }, + array: { $ref: '#/definitions/arrayDef' }, + }, + }; + const schemaWithRefs = { + type: 'object', + properties: { + string1: { $ref: '#/definitions/stringDef' }, + string2: { type: 'string' }, + number: { $ref: '#/definitions/numberDef' }, + int: { $ref: '#/definitions/intDef' }, + bool: { $ref: '#/definitions/boolDef' }, + array: { $ref: '#/definitions/arrayDef' }, + }, + }; + t.deepEqual(createDefaultValue(schemaWithRefs, rootSchemaWithRefs), { + string1: 'excellent', + number: 10, + int: 11, + bool: true, + array: ['a', 'b', 'c'], + }); }); test(`mapStateToJsonFormsRendererProps should use registered UI schema given ownProps schema`, (t) => { @@ -595,7 +728,7 @@ test('mapDispatchToArrayControlProps should adding items to array', (t) => { const [getCore, dispatch] = mockDispatch(initCore); dispatch(init(data, schema, uischema)); const props = mapDispatchToArrayControlProps(dispatch); - props.addItem('', createDefaultValue(schema))(); + props.addItem('', createDefaultValue(schema, schema))(); t.is(getCore().data.length, 2); }); @@ -1286,7 +1419,7 @@ test('should assign defaults to newly added item within nested object of an arra const [getCore, dispatch] = mockDispatch(initCore); dispatch(init(data, schema, uischema, createAjv({ useDefaults: true }))); const props = mapDispatchToArrayControlProps(dispatch); - props.addItem('', createDefaultValue(schema))(); + props.addItem('', createDefaultValue(schema, schema))(); t.is(getCore().data.length, 2); t.deepEqual(getCore().data[0], { message: 'foo' }); diff --git a/packages/examples/src/examples/arrays-with-defaults.ts b/packages/examples/src/examples/arrays-with-defaults.ts new file mode 100644 index 000000000..9ee4cb37f --- /dev/null +++ b/packages/examples/src/examples/arrays-with-defaults.ts @@ -0,0 +1,129 @@ +/* + The MIT License + + Copyright (c) 2023 STMicroelectronics + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the 'Software'), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +import { convertDateToString } from '@jsonforms/core'; +import { registerExamples } from '../register'; + +export const schema = { + definitions: { + itemsType: { + type: 'object', + properties: { + name: { + type: 'string', + default: 'foo1', + }, + name_noDefault: { + type: 'string', + }, + description: { + type: 'string', + default: 'bar', + }, + done: { + type: 'boolean', + default: false, + }, + rating: { + type: 'integer', + default: 5, + }, + cost: { + type: 'number', + default: 5.5, + }, + date: { + type: 'string', + format: 'date', + default: convertDateToString(new Date(), 'date'), + }, + }, + }, + stringDef: { type: 'string', default: 'excellent' }, + numberDef: { type: 'number', default: 10 }, + intDef: { type: 'integer', default: 11 }, + boolDef: { type: 'boolean', default: true }, + arrayDef: { type: 'array', default: ['a', 'b', 'c'] }, + }, + type: 'object', + properties: { + objectArray: { + type: 'array', + items: { + $ref: '#/definitions/itemsType', + }, + }, + stringArray: { + type: 'array', + items: { + type: 'string', + default: '123', + }, + }, + objectArrayWithPropertyRefs: { + type: 'array', + items: { + type: 'object', + properties: { + string1: { $ref: '#/definitions/stringDef' }, + string2: { type: 'string' }, + number: { $ref: '#/definitions/numberDef' }, + int: { $ref: '#/definitions/intDef' }, + bool: { $ref: '#/definitions/boolDef' }, + array: { $ref: '#/definitions/arrayDef' }, + }, + }, + }, + }, +}; + +export const uischema = { + type: 'VerticalLayout', + elements: [ + { + type: 'Control', + scope: '#/properties/objectArray', + }, + { + type: 'Control', + scope: '#/properties/stringArray', + }, + { + type: 'Control', + scope: '#/properties/objectArrayWithPropertyRefs', + }, + ], +}; + +export const data = {}; + +registerExamples([ + { + name: 'array-with-defaults', + label: 'Array with defaults', + data, + schema, + uischema, + }, +]); diff --git a/packages/examples/src/index.ts b/packages/examples/src/index.ts index 4245b78cb..f4c5ed51b 100644 --- a/packages/examples/src/index.ts +++ b/packages/examples/src/index.ts @@ -35,6 +35,7 @@ import * as arrayWithDetail from './examples/arrays-with-detail'; import * as arrayWithDetailAndRule from './examples/arrays-with-detail-and-rule'; import * as arrayWithCustomChildLabel from './examples/arrays-with-custom-element-label'; import * as arrayWithSorting from './examples/arrays-with-sorting'; +import * as arrayWithDefaults from './examples/arrays-with-defaults'; import * as stringArray from './examples/stringArray'; import * as categorization from './examples/categorization'; import * as stepper from './examples/categorization-stepper'; @@ -125,4 +126,5 @@ export { conditionalSchemaComposition, additionalErrors, issue_1884, + arrayWithDefaults, }; diff --git a/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx b/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx index 4c441d1fa..9b1f3a262 100644 --- a/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx +++ b/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx @@ -82,7 +82,7 @@ export const MaterialListWithDetailRenderer = ({ [setSelectedIndex] ); const handleCreateDefaultValue = useCallback( - () => createDefaultValue(schema), + () => createDefaultValue(schema, rootSchema), [createDefaultValue] ); const foundUISchema = useMemo( diff --git a/packages/material-renderers/src/complex/MaterialAnyOfRenderer.tsx b/packages/material-renderers/src/complex/MaterialAnyOfRenderer.tsx index 6b65a7b13..b40732fae 100644 --- a/packages/material-renderers/src/complex/MaterialAnyOfRenderer.tsx +++ b/packages/material-renderers/src/complex/MaterialAnyOfRenderer.tsx @@ -67,7 +67,10 @@ export const MaterialAnyOfRenderer = ({ if ( isEmpty(data) || typeof data === - typeof createDefaultValue(anyOfRenderInfos[newIndex].schema) + typeof createDefaultValue( + anyOfRenderInfos[newIndex].schema, + rootSchema + ) ) { setSelectedAnyOf(newIndex); } else { @@ -79,7 +82,10 @@ export const MaterialAnyOfRenderer = ({ ); const openNewTab = (newIndex: number) => { - handleChange(path, createDefaultValue(anyOfRenderInfos[newIndex].schema)); + handleChange( + path, + createDefaultValue(anyOfRenderInfos[newIndex].schema, rootSchema) + ); setSelectedAnyOf(newIndex); }; diff --git a/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx b/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx index d6cc99f24..76ac053c3 100644 --- a/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx +++ b/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx @@ -79,7 +79,10 @@ export const MaterialOneOfRenderer = ({ ); const openNewTab = (newIndex: number) => { - handleChange(path, createDefaultValue(oneOfRenderInfos[newIndex].schema)); + handleChange( + path, + createDefaultValue(oneOfRenderInfos[newIndex].schema, rootSchema) + ); setSelectedIndex(newIndex); }; diff --git a/packages/material-renderers/src/complex/TableToolbar.tsx b/packages/material-renderers/src/complex/TableToolbar.tsx index 04dc67f31..f85eda0d1 100644 --- a/packages/material-renderers/src/complex/TableToolbar.tsx +++ b/packages/material-renderers/src/complex/TableToolbar.tsx @@ -61,6 +61,7 @@ const TableToolbar = React.memo(function TableToolbar({ schema, enabled, translations, + rootSchema, }: MaterialTableToolbarProps) { return ( @@ -95,7 +96,7 @@ const TableToolbar = React.memo(function TableToolbar({ > diff --git a/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx b/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx index 578e0e070..40b7cbef2 100644 --- a/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx +++ b/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx @@ -38,7 +38,7 @@ import merge from 'lodash/merge'; const MaterialArrayLayoutComponent = (props: ArrayLayoutProps) => { const [expanded, setExpanded] = useState(false); const innerCreateDefaultValue = useCallback( - () => createDefaultValue(props.schema), + () => createDefaultValue(props.schema, props.rootSchema), [props.schema] ); const handleChange = useCallback( diff --git a/packages/vanilla-renderers/src/complex/TableArrayControl.tsx b/packages/vanilla-renderers/src/complex/TableArrayControl.tsx index a6c245b44..39fdefb9b 100644 --- a/packages/vanilla-renderers/src/complex/TableArrayControl.tsx +++ b/packages/vanilla-renderers/src/complex/TableArrayControl.tsx @@ -112,7 +112,7 @@ class TableArrayControl extends React.Component< diff --git a/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx b/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx index 4e2b1b0b2..b8fbbf825 100644 --- a/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx @@ -97,7 +97,7 @@ export const ArrayControl = ({ diff --git a/packages/vue-vanilla/src/array/ArrayListRenderer.vue b/packages/vue-vanilla/src/array/ArrayListRenderer.vue index 8f3fa3af0..5cc004e88 100644 --- a/packages/vue-vanilla/src/array/ArrayListRenderer.vue +++ b/packages/vue-vanilla/src/array/ArrayListRenderer.vue @@ -113,7 +113,7 @@ const controlRenderer = defineComponent({ addButtonClick() { this.addItem( this.control.path, - createDefaultValue(this.control.schema) + createDefaultValue(this.control.schema, this.control.rootSchema) )(); }, }, diff --git a/packages/vue-vanilla/src/complex/OneOfRenderer.vue b/packages/vue-vanilla/src/complex/OneOfRenderer.vue index f068f5856..0fce02b4a 100644 --- a/packages/vue-vanilla/src/complex/OneOfRenderer.vue +++ b/packages/vue-vanilla/src/complex/OneOfRenderer.vue @@ -176,7 +176,8 @@ const controlRenderer = defineComponent({ this.control.path, this.newSelectedIndex !== undefined && this.newSelectedIndex !== null ? createDefaultValue( - this.indexedOneOfRenderInfos[this.newSelectedIndex].schema + this.indexedOneOfRenderInfos[this.newSelectedIndex].schema, + this.control.rootSchema ) : {} ); @@ -193,4 +194,3 @@ export const entry: JsonFormsRendererRegistryEntry = { tester: rankWith(3, isOneOfControl), }; - \ No newline at end of file