diff --git a/packages/angular/src/library/abstract-control.ts b/packages/angular/src/library/abstract-control.ts index af43608ce..0dde8f657 100644 --- a/packages/angular/src/library/abstract-control.ts +++ b/packages/angular/src/library/abstract-control.ts @@ -29,7 +29,6 @@ import { JsonFormsState, JsonSchema, OwnPropsOfControl, - removeId, StatePropsOfControl, } from '@jsonforms/core'; import { Component, Input, OnDestroy, OnInit } from '@angular/core'; @@ -149,7 +148,6 @@ export abstract class JsonFormsAbstractControl< ngOnDestroy() { super.ngOnDestroy(); - removeId(this.id); } isEnabled(): boolean { diff --git a/packages/angular/src/library/jsonforms.component.ts b/packages/angular/src/library/jsonforms.component.ts index 22a93264b..6333b03c0 100644 --- a/packages/angular/src/library/jsonforms.component.ts +++ b/packages/angular/src/library/jsonforms.component.ts @@ -32,7 +32,7 @@ import { ViewContainerRef, } from '@angular/core'; import { - createId, + nextId, isControl, getConfig, JsonFormsProps, @@ -143,7 +143,7 @@ export class JsonFormsOutlet const controlInstance = instance as JsonFormsControl; if (controlInstance.id === undefined) { const id = isControl(props.uischema) - ? createId(props.uischema.scope) + ? nextId() + props.uischema.scope : undefined; (instance as JsonFormsControl).id = id; } diff --git a/packages/core/src/util/ids.ts b/packages/core/src/util/ids.ts index 4914754f4..34316019e 100644 --- a/packages/core/src/util/ids.ts +++ b/packages/core/src/util/ids.ts @@ -23,30 +23,21 @@ THE SOFTWARE. */ -const usedIds: Set = new Set(); +let idNamespace: string; +let idIndex: number; -const makeId = (idBase: string, iteration: number) => - iteration <= 1 ? idBase : idBase + iteration.toString(); - -const isUniqueId = (idBase: string, iteration: number) => { - const newID = makeId(idBase, iteration); - return !usedIds.has(newID); -}; - -export const createId = (proposedId: string) => { - if (proposedId === undefined) { - // failsafe to avoid endless loops in error cases - proposedId = 'undefined'; - } - let tries = 0; - while (!isUniqueId(proposedId, tries)) { - tries++; - } - const newID = makeId(proposedId, tries); - usedIds.add(newID); - return newID; +export const seedIds = (namespace = 'jsonforms', index = 0) => { + idNamespace = namespace; + idIndex = index; }; -export const removeId = (id: string) => usedIds.delete(id); +// This has a salt in the unlikely case that someone bundled multiple instances +// of this module on a single site. +seedIds(`jsonforms${Math.random().toString(32).slice(2)}`); -export const clearAllIds = () => usedIds.clear(); +/** + * Generate an ID that's unique within the current execution context. This is + * intended for HTML ID generation. Does not guarantee stability across SSR + * boundaries! + */ +export const nextId = () => `:${idNamespace}:${(idIndex++).toString(36)}:`; diff --git a/packages/core/test/mappers/cell.test.ts b/packages/core/test/mappers/cell.test.ts index c0317aa61..dd940a0d0 100644 --- a/packages/core/test/mappers/cell.test.ts +++ b/packages/core/test/mappers/cell.test.ts @@ -25,7 +25,7 @@ import test from 'ava'; import * as _ from 'lodash'; import * as Redux from 'redux'; -import { clearAllIds, createAjv, validate } from '../../src/util'; +import { seedIds, createAjv, validate } from '../../src/util'; import { UPDATE_DATA, UpdateAction } from '../../src/actions'; import configureStore from 'redux-mock-store'; import { JsonFormsState } from '../../src/store'; @@ -263,7 +263,7 @@ test('mapStateToCellProps - data', (t) => { }); test('mapStateToCellProps - id', (t) => { - clearAllIds(); + seedIds(); const ownProps = { uischema: coreUISchema, id: '#/properties/firstName', diff --git a/packages/core/test/mappers/renderer.test.ts b/packages/core/test/mappers/renderer.test.ts index 8e686e884..6ef1c6975 100644 --- a/packages/core/test/mappers/renderer.test.ts +++ b/packages/core/test/mappers/renderer.test.ts @@ -64,7 +64,7 @@ import { mapStateToOneOfEnumControlProps, mapStateToOneOfProps, } from '../../src/mappers'; -import { clearAllIds, convertDateToString, createAjv } from '../../src/util'; +import { seedIds, convertDateToString, createAjv } from '../../src/util'; import { rankWith } from '../../src'; const middlewares: Redux.Middleware[] = []; @@ -429,7 +429,7 @@ test('mapStateToControlProps - no duplicate error messages', (t) => { }); test('mapStateToControlProps - id', (t) => { - clearAllIds(); + seedIds(); const ownProps = { uischema: coreUISchema, id: '#/properties/firstName', diff --git a/packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx b/packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx index fc02b28e6..6e5add363 100644 --- a/packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx +++ b/packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx @@ -5,8 +5,6 @@ import React, { Fragment, ReducerAction, useMemo, - useState, - useEffect, useCallback, } from 'react'; import { @@ -25,8 +23,7 @@ import { update, JsonFormsCellRendererRegistryEntry, JsonFormsUISchemaRegistryEntry, - createId, - removeId, + nextId, ArrayTranslations, computeChildLabel, UpdateArrayContext, @@ -88,13 +85,8 @@ export interface ExpandPanelProps DispatchPropsOfExpandPanel {} const ExpandPanelRendererComponent = (props: ExpandPanelProps) => { - const [labelHtmlId] = useState(createId('expand-panel')); - - useEffect(() => { - return () => { - removeId(labelHtmlId); - }; - }, [labelHtmlId]); + // TODO: Should probably use React.useId() when support for React < 18 is dropped. + const labelHtmlId = useMemo(() => nextId() + 'expand-panel', []); const { enabled, diff --git a/packages/react/src/JsonForms.tsx b/packages/react/src/JsonForms.tsx index 38ed5514d..4262fa7f8 100644 --- a/packages/react/src/JsonForms.tsx +++ b/packages/react/src/JsonForms.tsx @@ -28,9 +28,8 @@ import type Ajv from 'ajv'; import type { ErrorObject } from 'ajv'; import { UnknownRenderer } from './UnknownRenderer'; import { - createId, + nextId, Generate, - isControl, JsonFormsCellRendererRegistryEntry, JsonFormsCore, JsonFormsI18nState, @@ -40,7 +39,6 @@ import { JsonSchema, Middleware, OwnPropsOfJsonFormsRenderer, - removeId, UISchemaElement, ValidationMode, } from '@jsonforms/core'; @@ -49,129 +47,57 @@ import { withJsonFormsRendererProps, } from './JsonFormsContext'; -interface JsonFormsRendererState { - id: string; -} - export interface JsonFormsReactProps { onChange?(state: Pick): void; middleware?: Middleware; } -export class JsonFormsDispatchRenderer extends React.Component< - JsonFormsProps, - JsonFormsRendererState -> { - constructor(props: JsonFormsProps) { - super(props); - this.state = { - id: isControl(props.uischema) - ? createId(props.uischema.scope) - : undefined, - }; - } - - componentWillUnmount() { - if (isControl(this.props.uischema)) { - removeId(this.state.id); - } - } - - componentDidUpdate(prevProps: JsonFormsProps) { - if (prevProps.schema !== this.props.schema) { - removeId(this.state.id); - this.setState({ - id: isControl(this.props.uischema) - ? createId(this.props.uischema.scope) - : undefined, - }); - } - } - - render() { - const { - schema, - rootSchema, - uischema, - path, - enabled, - renderers, - cells, - config, - } = this.props as JsonFormsProps; - - return ( - +export const JsonFormsDispatchRenderer = React.memo( + function JsonFormsDispatchRenderer(props: JsonFormsProps) { + // TODO: Should probably use React.useId() when support for React < 18 is dropped. + const id = useMemo(nextId, [props.schema]); + const testerContext = useMemo( + () => ({ + rootSchema: props.rootSchema, + config: props.config, + }), + [props.rootSchema, props.config] ); - } -} - -const TestAndRender = React.memo(function TestAndRender(props: { - uischema: UISchemaElement; - schema: JsonSchema; - rootSchema: JsonSchema; - path: string; - enabled: boolean; - renderers: JsonFormsRendererRegistryEntry[]; - cells: JsonFormsCellRendererRegistryEntry[]; - id: string; - config: any; -}) { - const testerContext = useMemo( - () => ({ - rootSchema: props.rootSchema, - config: props.config, - }), - [props.rootSchema, props.config] - ); - const renderer = useMemo( - () => - maxBy(props.renderers, (r) => - r.tester(props.uischema, props.schema, testerContext) - ), - [props.renderers, props.uischema, props.schema, testerContext] - ); - if ( - renderer === undefined || - renderer.tester(props.uischema, props.schema, testerContext) === -1 - ) { - return ; - } else { - const Render = renderer.renderer; - return ( - + const renderer = useMemo( + () => + maxBy(props.renderers, (r) => + r.tester(props.uischema, props.schema, testerContext) + ), + [props.renderers, props.uischema, props.schema, testerContext] ); + if ( + renderer === undefined || + renderer.tester(props.uischema, props.schema, testerContext) === -1 + ) { + return ; + } else { + const Render = renderer.renderer; + return ( + + ); + } } -}); +); /** * @deprecated Since Version 3.0 this optimization renderer is no longer necessary. * Use `JsonFormsDispatch` instead. * We still export it for backward compatibility */ -export class ResolvedJsonFormsDispatchRenderer extends JsonFormsDispatchRenderer { - constructor(props: JsonFormsProps) { - super(props); - } -} +export const ResolvedJsonFormsDispatchRenderer = JsonFormsDispatchRenderer; export const JsonFormsDispatch: ComponentType = withJsonFormsRendererProps(JsonFormsDispatchRenderer); diff --git a/packages/vue-vuetify/tests/unit/additional/LabelRenderer.spec.ts b/packages/vue-vuetify/tests/unit/additional/LabelRenderer.spec.ts index c7220b47c..35e0d4fc0 100644 --- a/packages/vue-vuetify/tests/unit/additional/LabelRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/additional/LabelRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import LabelRenderer from '../../../src/additional/LabelRenderer.vue'; import { entry as labelRendererEntry } from '../../../src/additional/LabelRenderer.entry'; import { mountJsonForms } from '../util'; @@ -20,7 +20,7 @@ describe('LabelRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/additional/ListWithDetailRenderer.spec.ts b/packages/vue-vuetify/tests/unit/additional/ListWithDetailRenderer.spec.ts index 190b5ff49..25a9e1e65 100644 --- a/packages/vue-vuetify/tests/unit/additional/ListWithDetailRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/additional/ListWithDetailRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds, type Translator } from '@jsonforms/core'; +import { seedIds, type Translator } from '@jsonforms/core'; import ListWithDetailRenderer from '../../../src/additional/ListWithDetailRenderer.vue'; import { entry as listWithDetailRendererEntry } from '../../../src/additional/ListWithDetailRenderer.entry'; import { mountJsonForms } from '../util'; @@ -28,7 +28,7 @@ describe('ListWithDetailRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema, undefined, { translate: ((id, defaultMessage) => { if (id.endsWith('addAriaLabel')) { diff --git a/packages/vue-vuetify/tests/unit/complex/ArrayControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/complex/ArrayControlRenderer.spec.ts index 0422ca64f..a45cca58a 100644 --- a/packages/vue-vuetify/tests/unit/complex/ArrayControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/complex/ArrayControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds, type Translator } from '@jsonforms/core'; +import { seedIds, type Translator } from '@jsonforms/core'; import ArrayControlRenderer from '../../../src/complex/ArrayControlRenderer.vue'; import { entry as arrayControlRendererEntry } from '../../../src/complex/ArrayControlRenderer.entry'; import { mountJsonForms } from '../util'; @@ -27,7 +27,7 @@ describe('ArrayControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema, undefined, { translate: ((id, defaultMessage) => { if (id.endsWith('addAriaLabel')) { diff --git a/packages/vue-vuetify/tests/unit/complex/OneOfRenderer.spec.ts b/packages/vue-vuetify/tests/unit/complex/OneOfRenderer.spec.ts index 9cae6a50e..ee2349a23 100644 --- a/packages/vue-vuetify/tests/unit/complex/OneOfRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/complex/OneOfRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds, type Translator } from '@jsonforms/core'; +import { seedIds, type Translator } from '@jsonforms/core'; import OneOfControlRenderer from '../../../src/complex/OneOfRenderer.vue'; import { entry as oneOfControlRendererEntry } from '../../../src/complex/OneOfRenderer.entry'; import { mountJsonForms } from '../util'; @@ -38,7 +38,7 @@ describe('OneOfRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema, undefined, { translate: ((id, defaultMessage) => { if (id.endsWith('clearDialogAccept')) { diff --git a/packages/vue-vuetify/tests/unit/controls/BooleanControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/BooleanControlRenderer.spec.ts index 1c1c592a0..08e1ef2d2 100644 --- a/packages/vue-vuetify/tests/unit/controls/BooleanControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/BooleanControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import BooleanControlRenderer from '../../../src/controls/BooleanControlRenderer.vue'; import { entry as booleanControlRendererEntry } from '../../../src/controls/BooleanControlRenderer.entry'; import { mountJsonForms } from '../util'; @@ -23,7 +23,7 @@ describe('BooleanControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/DateControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/DateControlRenderer.spec.ts index 4365a8486..04e6484dd 100644 --- a/packages/vue-vuetify/tests/unit/controls/DateControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/DateControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import DateControlRenderer from '../../../src/controls/DateControlRenderer.vue'; import { entry as dateControlRendererEntry } from '../../../src/controls/DateControlRenderer.entry'; import { mountJsonForms } from '../util'; @@ -27,7 +27,7 @@ describe('DateControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/DateTimeControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/DateTimeControlRenderer.spec.ts index 08f994643..05ec9947b 100644 --- a/packages/vue-vuetify/tests/unit/controls/DateTimeControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/DateTimeControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import DateTimeControlRenderer from '../../../src/controls/DateTimeControlRenderer.vue'; import { entry as dateTimeControlRendererEntry } from '../../../src/controls/DateTimeControlRenderer.entry'; import { mountJsonForms } from '../util'; @@ -26,7 +26,7 @@ describe('DateTimeControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/EnumControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/EnumControlRenderer.spec.ts index 9f9c19c33..9c391e010 100644 --- a/packages/vue-vuetify/tests/unit/controls/EnumControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/EnumControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import EnumControlRenderer from '../../../src/controls/EnumControlRenderer.vue'; import { entry as enumControlRendererEntry } from '../../../src/controls/EnumControlRenderer.entry'; import { wait } from '../../../tests'; @@ -24,7 +24,7 @@ describe('EnumControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/IntegerControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/IntegerControlRenderer.spec.ts index ef64f124a..88c01f448 100644 --- a/packages/vue-vuetify/tests/unit/controls/IntegerControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/IntegerControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import IntegerControlRenderer from '../../../src/controls/IntegerControlRenderer.vue'; import { entry as integerControlRendererEntry } from '../../../src/controls/IntegerControlRenderer.entry'; import { wait } from '../../../tests'; @@ -24,7 +24,7 @@ describe('IntegerControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/MultiStringControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/MultiStringControlRenderer.spec.ts index 77a6b14e9..3c6703acc 100644 --- a/packages/vue-vuetify/tests/unit/controls/MultiStringControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/MultiStringControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import MultiStringControlRenderer from '../../../src/controls/MultiStringControlRenderer.vue'; import { entry as multiStringControlRendererEntry } from '../../../src/controls/MultiStringControlRenderer.entry'; import { wait } from '../../../tests'; @@ -25,7 +25,7 @@ describe('MultiStringControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/NumberControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/NumberControlRenderer.spec.ts index 0f76ffd83..8121e50a4 100644 --- a/packages/vue-vuetify/tests/unit/controls/NumberControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/NumberControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import NumberControlRenderer from '../../../src/controls/NumberControlRenderer.vue'; import { entry as numberControlRendererEntry } from '../../../src/controls/NumberControlRenderer.entry'; import { wait } from '../../../tests'; @@ -23,7 +23,7 @@ describe('NumberControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/OneOfEnumControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/OneOfEnumControlRenderer.spec.ts index f8f293037..2942b31fb 100644 --- a/packages/vue-vuetify/tests/unit/controls/OneOfEnumControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/OneOfEnumControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import OneOfEnumControlRenderer from '../../../src/controls/OneOfEnumControlRenderer.vue'; import { entry as oneOfEnumControlRendererEntry } from '../../../src/controls/OneOfEnumControlRenderer.entry'; import { wait } from '../../../tests'; @@ -26,7 +26,7 @@ describe('OneOfEnumControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/StringControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/StringControlRenderer.spec.ts index 345f9287d..39bfa75af 100644 --- a/packages/vue-vuetify/tests/unit/controls/StringControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/StringControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import StringControlRenderer from '../../../src/controls/StringControlRenderer.vue'; import { entry as stringControlRendererEntry } from '../../../src/controls/StringControlRenderer.entry'; import { wait } from '../../../tests'; @@ -25,7 +25,7 @@ describe('StringControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); @@ -91,7 +91,7 @@ describe('StringControlRenderer.vue with suggestion', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/controls/TimeControlRenderer.spec.ts b/packages/vue-vuetify/tests/unit/controls/TimeControlRenderer.spec.ts index 556200c44..d9cd8b871 100644 --- a/packages/vue-vuetify/tests/unit/controls/TimeControlRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/controls/TimeControlRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds } from '@jsonforms/core'; +import { seedIds } from '@jsonforms/core'; import TimeControlRenderer from '../../../src/controls/TimeControlRenderer.vue'; import { entry as timeControlRendererEntry } from '../../../src/controls/TimeControlRenderer.entry'; import { mountJsonForms } from '../util'; @@ -25,7 +25,7 @@ describe('TimeControlRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema); }); diff --git a/packages/vue-vuetify/tests/unit/layout/ArrayLayoutRenderer.spec.ts b/packages/vue-vuetify/tests/unit/layout/ArrayLayoutRenderer.spec.ts index ba8a591c5..fa1d684f1 100644 --- a/packages/vue-vuetify/tests/unit/layout/ArrayLayoutRenderer.spec.ts +++ b/packages/vue-vuetify/tests/unit/layout/ArrayLayoutRenderer.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { clearAllIds, type Translator } from '@jsonforms/core'; +import { seedIds, type Translator } from '@jsonforms/core'; import ArrayLayoutRenderer from '../../../src/layouts/ArrayLayoutRenderer.vue'; import { entry as arrayLayoutRendererEntry } from '../../../src/layouts/ArrayLayoutRenderer.entry'; import { mountJsonForms } from '../util'; @@ -28,7 +28,7 @@ describe('ArrayLayoutRenderer.vue', () => { beforeEach(() => { // clear all ids to guarantee that the snapshots will always be generated with the same ids - clearAllIds(); + seedIds(); wrapper = mountJsonForms(data, schema, renderers, uischema, undefined, { translate: ((id, defaultMessage) => { if (id.endsWith('addAriaLabel')) { diff --git a/packages/vue/src/jsonFormsCompositions.ts b/packages/vue/src/jsonFormsCompositions.ts index 1ac967aab..dbb366230 100644 --- a/packages/vue/src/jsonFormsCompositions.ts +++ b/packages/vue/src/jsonFormsCompositions.ts @@ -29,8 +29,7 @@ import { mapStateToDispatchCellProps, mapStateToOneOfEnumCellProps, StatePropsOfJsonFormsRenderer, - createId, - removeId, + nextId, mapStateToMultiEnumControlProps, mapDispatchToMultiEnumProps, mapStateToLabelProps, @@ -197,7 +196,7 @@ export function useControl< onBeforeMount(() => { if (control.value.uischema.scope) { - id.value = createId(control.value.uischema.scope); + id.value = nextId() + control.value.uischema.scope; } }); @@ -205,17 +204,13 @@ export function useControl< () => props.schema, (newSchema, prevSchem) => { if (newSchema !== prevSchem && isControl(control.value.uischema)) { - if (id.value) { - removeId(id.value); - } - id.value = createId(control.value.uischema.scope); + id.value = nextId() + control.value.uischema.scope; } } ); onUnmounted(() => { if (id.value) { - removeId(id.value); id.value = undefined; } });