# Root OneOf Renderer

**URL:** <https://jsonforms.discourse.group/t/root-oneof-renderer/1793>\
**Category:** General\
**Created:** [October 27, 2023, 5:31pm UTC](https://jsonforms.discourse.group/t/root-oneof-renderer/1793 "2023-10-27T17:31:48Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![andperks](https://avatars.discourse-cdn.com/v4/letter/a/ecb155/32.png) [@andperks](https://jsonforms.discourse.group/u/andperks)\
**Post date:** [October 27, 2023, 5:31pm UTC](https://jsonforms.discourse.group/t/root-oneof-renderer/1793/1 "2023-10-27T17:31:48Z")

</div>

I have a schema that has a conditional subschema called ‘config’ based on a dataset ‘type’. Following advice from other posts on the forum I have restructured if/then stanzas in my schema to a oneOf but

First, similar to described [here](https://github.com/eclipsesource/jsonforms/issues/1518#issuecomment-553772846). However this gives a ‘no applicable renderer found’ even if I explicitly specify a oneOfControl variant for the tester. The issue is not the renderer as I am using a variant of vue-vanilla renderers that works in a subsequent example.

```auto
 {
                      "type": "Control",
                      "scope": "#/oneOf",
                      "options": {
                          "readonly": false,
                          "variant": "oneOfControl",

                      },
                  },

```

Second, I followed the second suggestion of using UISchema rules. I have the following under the scope of #/properties:

```auto
"type": {
  "title": "Dataset type",
  "enum": ["DATASET_TYPE1", "DATASET_TYPE2", "DATASET_TYPE3", "DATASET_TYPE4", "DATASET_TYPE5"]
},
"config": {
  "oneOf": [
      {
          "$ref": "#/$defs/dataset1"
      },
      {
          "$ref": "#/$defs/dataset2"
      },
      {
          "$ref": "#/$defs/dataset3"
      },

      {
          "$ref": "#/$defs/dataset4"
      },
      {
          "$ref": "#/$defs/dataset5"
      }
  ]
}

```

And a UISchema to conditionally display

```auto
    {
                            "type": "Group",
                            "elements": [
                                {
                                    "type": "Control",
                                    "label": "Dataset 1 Config",
                                    "scope": "#/properties/config/oneOf[0]",
                                    "rule": {
                                        "effect": "SHOW",
                                        "condition": {
                                            "scope": "#/properties/type",
                                            "schema": {
                                                "const": "DATASET_TYPE1"
                                            }
                                        }
                                    }
                                }
                            ]
                        }

```

but get a syntax error

```auto
SyntaxError: Identifier 'schema1' has already been declared

```

Finally, the closest to my result is emulating the [vuetify oneOf-tab example](https://github.com/eclipsesource/jsonforms-vuetify-renderers/blob/1ca0fc47848e49b714887abb6c4de622c96f6369/example/src/examples/oneOf-tab/schema.json) by nesting the oneOf under an object property like so.

```auto
   "type": {
            "oneOf": [
                {
                    "title": "DATASET_1",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "DATASET_1"
                        },
                        "config": {
                            "$ref": "#/$defs/dataset1"
                        }
                    }
                },
]}

```

And this renders as expected but as it is a nested property, no longer binds with form data. Based on these

1. Is there a correct way to declare a oneOf control in the UISchema (that is not nested under a property)?
2. Am I missing a ‘correct’ syntax for displaying an indexed item in the oneOf?
3. If I must nest the oneOf, is there a way to specify what data to bind to (e.g., the “type” and “config” properties under “type” should bind to root level data)?

---

<div class="post-metadata">

**Author:** ![lucas-koehler](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/lucas-koehler/32/336_2.png) [@lucas-koehler](https://jsonforms.discourse.group/u/lucas-koehler)\
**Post date:** [October 31, 2023, 2:35pm UTC](https://jsonforms.discourse.group/t/root-oneof-renderer/1793/2 "2023-10-31T14:35:28Z")

</div>

Hi @andperks ,  
our workload is currently quite high and we do not have time to investigate this. We will come back to your questions later though 🙂

Until then, I have one question: Is there some property or anything else named `schema1` in you schema or UI Schema. I ask because it’s mentioned in the syntax error.

Best regards,  
Lucas

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [October 31, 2023, 4:30pm UTC](https://jsonforms.discourse.group/t/root-oneof-renderer/1793/3 "2023-10-31T16:30:24Z")

</div>

Hi @andperks,

> [@andperks](#):
>
> `"scope": "#/properties/config/oneOf[0]"`

This is not a valid JSON Pointer, you should try `#/properties/config/oneOf/0`

> [@andperks](#):
>
> `SyntaxError: Identifier 'schema1' has already been declared`

Is this an error coming from AJV?

- If yes, can you try to remove the `id` or `$id` attribute in your JSON Schema? There is an open PR related to this in the repo: [fix(core): Disable schema caching in AJV instance by LukasBoll · Pull Request #2201 · eclipsesource/jsonforms · GitHub](https://github.com/eclipsesource/jsonforms/pull/2201)
- If no, if that is an error in the JSON Forms code please paste the full strack trace and/or open an issue against the repository

> [@andperks](#):
>
> ```auto
> "type": {
> "oneOf": [
> {
> "title": "DATASET_1",
> "type": "object",
> "properties": {
> "type": {
> "const": "DATASET_1"
> },
> "config": {
> "$ref": "#/$defs/dataset1"
> }
> }
> },
> ]}
> 
> ```
> 
> And this renders as expected but as it is a nested property, no longer binds with form data.

The structure is not fully correct here. You had `type/config` as siblings in the original. So you should move the `oneOf` one level higher and remove the root `config`. Regarding the non-binding: We don’t handle the atttributes which just consists of a `const` that well as they typically don’t make sense for a form.

Generally speaking all of these structures should work. Note that you also always have the option to write a custom renderer specialized for your used structures in the JSON Schema so you can add exactly the behavior you need. For example the `const` property of the last example could be nicely supported by a custom `oneOf` renderer which then automatically sets this property when needed. You don’t _have to_ create a custom renderer, however for example maintaining a lot of UI Schema rules also comes with a cost.

---

<div class="post-metadata">

**Author:** ![andperks](https://avatars.discourse-cdn.com/v4/letter/a/ecb155/32.png) [@andperks](https://jsonforms.discourse.group/u/andperks)\
**Post date:** [October 31, 2023, 8:17pm UTC](https://jsonforms.discourse.group/t/root-oneof-renderer/1793/4 "2023-10-31T20:17:03Z")

</div>

Thanks for the response, I was able to resolve this by

1. moving the oneOf to the root level
2. forcing the OneOfRenderer by creating a ‘OneOfControl’ variant tester
3. before calling `createCombinatorRenderInfos` in the renderer, checking if `this.control.schema.oneOf `is defined before passing. I think the core issue here is when a OneOf is nested in the root level of a schema (or maybe specified in the UISchema like `#/oneOf` ), the schema that is passed to the renderer is not longer nested under `this.control.schema.oneOf`

Still working on how to identify the default index to render as `indexOfFittingSchema` always appears undefined but I consider this solved.

In case it helps anyone else, I’ll leave context on the issue with conditional visibility rules in the UISchema below:

> [@sdirix](#):
>
> This is not a valid JSON Pointer, you should try `#/properties/config/oneOf/0`

Ah I was only following the syntax in [this thread](https://github.com/eclipsesource/jsonforms/issues/1518#issuecomment-553835987). I did try using the valid pointer `#/properties/config/oneOf/0` but received the same syntaxError. It does appear to be an error from AJV but removing `$id` from the schema did not solve the issue. Here is the relevant part of the stack trace:

```auto
compileSchema	@	index.ts:171
_compileMetaSchema	@	core.ts:744
_compileSchemaEnv	@	core.ts:732
getSchema	@	core.ts:536
defaultMeta	@	ajv.ts:30
validateSchema	@	core.ts:509
_addSchema	@	core.ts:721
compile	@	core.ts:384
validate	@	core.ts:361
evaluateCondition	@	runtime.ts:82
isRuleFulfilled	@	runtime.ts:96
evalVisibility	@	runtime.ts:105
isVisible	@	runtime.ts:166
mapStateToControlProps	@	renderer.ts:459
mapStateToControlWithDetailProps	@	renderer.ts:707
(anonymous)	@	jsonFormsCompositions.ts:174
run	@	reactivity.esm-bundler.js:178
get value	@	reactivity.esm-bundler.js:1147
useVanillaControl	@	composition.ts:45
setup	@	ObjectRenderer.vue:45

```

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [November 6, 2023, 10:10am UTC](https://jsonforms.discourse.group/t/root-oneof-renderer/1793/5 "2023-11-06T10:10:55Z")

</div>

Hi @andperks,

> [@andperks](#):
>
> It does appear to be an error from AJV but removing `$id` from the schema did not solve the issue. Here is the relevant part of the stack trace:

Are you sure there is no `id` or `$id` property in your JSON Schema left? You can also hand over a custom instance of AJV to JSON Forms [in which the whole id checking is disabled](https://ajv.js.org/options.html#addusedschema).

> [@andperks](#):
>
> before calling `createCombinatorRenderInfos` in the renderer, checking if `this.control.schema.oneOf `is defined before passing.

> [@andperks](#):
>
> Still working on how to identify the default index to render as `indexOfFittingSchema` always appears undefined but I consider this solved.

If you can avoid calling `createCombinatorRenderInfos`, then please do so. In there we validate all the sub schemas to maybe determine which one fits to the data presented. If your data contains some unique property on which you can decide which sub schema (i.e. index) shall be used, then implement this manually. This will avoid the need of compiling and validating sub schemas, saving a lot in initial rendering performance.
