How to integrate Dynamic JSON Schemas with JSONForms in a Vue2 Application

Hi,
I’m currently developing a front-end application using the Vue2 framework and encountering a challenge with integrating JSONForms. My application needs to dynamically generate forms based on JSON schemas provided by a backend API. The complexity arises because the schema of the form changes depending on various conditions.

Specifically, the application presents a list of product IDs. When a user selects an ID, the backend service sends a corresponding JSON schema. While I have managed to create forms using JSONForms within Vue2, I’m struggling to apply a UISchema effectively due to the variability in form properties. Additionally, I’ve noticed that JSONForms seems to have trouble recognising schemas with nested objects (type: object with properties). Let me know if you need a sample json schema to understand better.

I’m seeking guidance or examples that demonstrate how to handle dynamic JSON schemas in this context, particularly focusing on the appropriate use of UISchema or renderers within JSONForms for Vue2.

Note: I am relatively new to both Vue and JSONForms, so detailed explanations or references to resources would be greatly appreciated.

Thank you in advance for your assistance.

Hi @Urvashi,

If the JSON Schema is unknown beforehand then many users of JSON Forms don’t use a predefined UI Schema at all. Instead they use custom renderers which know about the common patterns in their JSON Schemas and render accordingly.

In general I’m not aware of any problem with nested objects. Can you elaborate what you are referring to?

I think it would be best if you could post a concrete example of the issues you are facing. It’s hard to give any generic advice here.

Note that we’re phasing out the support of Vue 2. The current stable release of JSON Forms will continue to work with Vue 2 but going forward the Vue 2 bindings and renderers will not receive any updates. Instead we’re focusing on Vue 3+

This is a sample of the json schema that I am using . Similarly there are other schemas with different fields based on the user input on the previous page.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Product ID",
  "properties": {
    "suite": {
      "type": "string",
      "description": "Suite",
      "enum": [
        "PRICING_TEST",
        "PRICING_DYNAMIC",
        "E2E",
        "E2E_TIME_PERIOD"
      ]
    },
    "tag": {
      "type": "string",
      "description": "Tag",
      "examples": [
        "e2e-supplier-api-avail-and-pricing"
      ]
    },
    "currency": {
      "type": "string",
      "description": "Currency",
      "examples": [
        "EUR"
      ]
    },
    "ticketType": {
      "type": "string",
      "description": "Ticket Type",
      "enum": [
        "TEXT",
        "BARCODE_CODE39",
        "BARCODE_CODE128",
        "QR_CODE",
        "DATA_MATRIX",
        "EAN_13",
        "ITF",
        "PDF_FILE",
        "AZTEC"
      ]
    },
    "ticketCode": {
      "type": "string",
      "description": "Ticket Code"
    },
    "vacancies": {
      "type": "number",
      "description": "Vacancies",
      "examples": [
        100
      ]
    },
    "pricesByCategory": {
      "type": "object",
      "properties": {
        "ADULT": {
          "type": "number"
        },
        "CHILD": {
          "type": "number"
        },
        "YOUTH": {
          "type": "number"
        },
        "INFANT": {
          "type": "number"
        },
        "SENIOR": {
          "type": "number"
        },
        "STUDENT": {
          "type": "number"
        }
      },
      "description": "Category mapping"
    },
    "data": {
      "type": "object",
      "properties": {
        "configuration": {
          "type": "string",
          "description": "Configuration"
        },
        "cutoffSeconds": {
          "type": "number",
          "description": "Cut-off Seconds"
        },
        "errorCode": {
          "type": "string",
          "description": "Error code",
          "examples": [
            "VALIDATION_FAILURE"
          ]
        },
        "method": {
          "type": "string",
          "description": "Method",
          "enum": [
            "get-vacancies",
            "addToCart",
            "removeFromCart",
            "confirm",
            "cancel-confirm",
            "notify"
          ]
        }
      }
    }
  }
}

After using both vanillaRenderes and VuetifyRenderes together, getting this type of form on the FE.

  1. Can you suggest a better solution (better renderer) in order to improve how form looks on the FE. e.g. there are no borders on the text box. I haven’t added a UI Schema as it is based on the fields of the form, that keeps changing in my use case based on the user input on the previous page

  2. Can you also suggest how to control the input in each fields without Using UI schema? For example if the minLength is 3 and user only enters 2 characters, then put a red alert below the text box.
    Similarly control for the String and Integer fields?

In the other schemas , we also have fields with type : “array”, e.g. -

"startTime": {
      "type": "array",
      "description": "Start time",
      "examples": [
        "09:00"
      ]
    },

Does JSON Forms supports string array , and not the key value pair array i.e. { 0 : 09:00 , 1 : 11:00 } ??

Additional Note : We are soon going to migrate to Vue3 , thats why I chose JSONForms as it compatible with both Vue2 and Vue3 .

The idea behind the “Vanilla” renderers is that the user can style them however they want. We don’t apply any styling ourselves. So if there are no border around the rendered inputs, then that is caused by some pre existing styling of the HTML / web app JSON Forms is integrated into

This is controlled via JSON Schema anyway. See for example here in the official docs.

Yes, array is supported. However you also need to specify the items of an array as otherwise JSON Forms doesn’t know how the array items look like. examples is not an official keyword and therefore ignored by JSON Forms.

Got it, thanks :+1:
I have removed vuetifyRenderers and using only vanillaRenderers now.

So is this the right way to render type : array with vanilla renderers ?

"startTime": {
      "type": "array",
      "description": "Start time",
      "items" : {
         "type": "string",
       }
    },

Also another question:
Since vanillaRenderers does not support type “object” , can you suggest an example of a custom renderer that I can simply use in my app for the type : object.
for example

"data": {
      "type": "object",
      "properties": {
        "configuration": {
          "type": "string",
          "description": "Configuration"
        },
        "cutoffSeconds": {
          "type": "number",
          "description": "Cut-off Seconds"
        },
        "errorCode": {
          "type": "string",
          "description": "Error code",
          "examples": [
            "VALIDATION_FAILURE"
          ]
        },
        "method": {
          "type": "string",
          "description": "Method",
          "enum": [
            "get-vacancies",
            "addToCart",
            "removeFromCart",
            "confirm",
            "cancel-confirm",
            "notify"
          ]
        }
      }
    }

This should work :+1:

Since vanillaRenderers does not support type “object” , can you suggest an example of a custom renderer that I can simply use in my app for the type : object.

The Vanilla Renderers support type: 'object' directly since July, so any of the prereleases, like the currently latest one 3.2.0-alpha.3, should work out of the box.

Isn’t version 3.2.0-alpha.3 of @jsonforms/vanilla-renderers compatible with react framework?
My app is based on Vue framework hence I am using @jsonforms/vue2-vuetify, which library and version is available for Vue (especiallu Vue2) ??
I am currently using
import { vanillaRenderers } from "@jsonforms/vue2-vanilla";

"@jsonforms/core": "3.0.0",
 "@jsonforms/vue2": "3.0.0",
"@jsonforms/vue2-vanilla": "3.0.0",

I get this form rendered with the above config, last 2 fields with type : “object” are not rendered.

You’re right, vue2-vanilla does not contain the object renderer as its last published version is 3.1.0. However the object renderer is quite simple, you can copy the one for Vue 3, adapt it if necessary and then register it as a custom renderer.

This solution worked with vue2-vanilla. Thanks for the support :slightly_smiling_face:

I have a question related to “description” keyword for each field. In the vanillaReneders that I am using , description is showed when the textbox or checkbox is clicked e.g. like this

"form": {
      "type": "boolean",
      "description": "Is required to send traveler email and country?"
},

Is there another way to display the description on the form e.g. display the description when hover on the field name?
Especially with the boolean variables as I have click on the check box in order to see the description of that field.

For types “object” and “array” , description is not visible even after I click on the component.

HI @Urvashi,

At the moment the description is only rendered when the respective input is focused, see here. The ControlWrapper is used by all controls, see for example here or here. To customize this on your side, you need to register a custom renderer which can then use its own custom ControlWrapper (or none at all).

If you want to adjust it for all renderers at the same time, you will need to register a custom renderer for each of them. We have an open issue to allow for easier customization of the ControlWrapper, see #1927. If you, or someone else, would like to contribute this functionality then we’ll happily accept that.

For now, you could just copy all basic renderers and adjust them to your liking. Over time that is what often happens anyway as more detailed requirements pop up in the respective use cases.