Custom Renderer Multiple Inputs AJV Errors

So I have a need for multiple custom renderers, some of which contain multiple inputs that belong to the same schema property.
This is what I did for one of them specifically and currently the one I need help with:

<template>
    <v-text-field v-model="firstName" placeholder="First Name" @input="sendToUpstream" />
    <v-text-field v-model="lastName" placeholder="Last Name" @input="sendToUpstream" />
</template>

<script lang="ts">
import { ControlElement, JsonFormsRendererRegistryEntry, rankWith, scopeEndsWith } from '@jsonforms/core'
import { useJsonFormsControl, RendererProps, rendererProps } from '@jsonforms/vue'
import { defineComponent } from 'vue'
import { useVanillaControl } from '@jsonforms/vue-vanilla'

const applyFormRenderName = defineComponent({
    name: 'apply-form-render-name',
    props: {
        ...rendererProps<ControlElement>(),
    },
    setup (props: RendererProps<ControlElement>) {
        const data = useVanillaControl(useJsonFormsControl(props), target => target.value || undefined)
        const firstName = ref(data.control.data?.firstName || '')
        const lastName = ref(data.control.data?.lastName || '')
        return {
            firstName,
            lastName,
            ...data,
        }
    },
    methods: {
        sendToUpstream () {
            if (this.firstName) {
                this.handleChange(this.control.path, {
                    ...this.control.data,
                    firstName: this.firstName,
                })
            }
            if (this.lastName) {
                this.handleChange(this.control.path, {
                    ...this.control.data,
                    lastName: this.lastName,
                })
            }
        },
    },
})

export default applyFormRenderName

export const entry: JsonFormsRendererRegistryEntry = {
    renderer: applyFormRenderName,
    tester: rankWith(2, scopeEndsWith('name')),
}
</script>

However, I’ve noticed that for AJV errors this doesn’t really work, since if I fill in at least one of the fields, no more errors show up. So this is probably not the best way to create this. Any suggestions on how I should do this or what I need to change so AJV works properly?

Here is the schema corresponding to this:

{
    "-personal-name": {
      "title": "Name",
      "description": "First and last name",
      "type": "object",
      "properties": {
        "first": {
          "type": "string",
          "minLength": 2,
          "maxLength": 30
        },
        "last": {
          "type": "string",
          "minLength": 2,
          "maxLength": 30
        }
      },
      "required": [
        "first",
        "last"
      ]
    },
}

Here is the UISchema for this property:

{"type":"Control","scope":"#/properties/-personal-name","options":{}}

Note: I’ve tried checking the ObjectRenderer in the Vue2 Vuetify renderer sets. I’m not sure I understood what is there, but do I basically need to use the DispatchRenderer component for each of the sub-schemas for AJV to work?

Hi @adamsilva01,

Yes, dispatching is the way to go. One would only create a renderer like you posted in cases there is something special about the object and its properties which would require handling them within one single renderer.

What’s missing here is an object renderer which creates a new UI Schema for the contained properties and dispatches to them. This is the corresponding renderer in React. The same functionality has to be implemented in Vue.

1 Like

Hey @sdirix ,

Apologies for the delay in answering. I managed to adapt the Vuetify2 Object renderer.

Just a question regarding what you said:

One would only create a renderer like you posted in cases there is something special about the object and its properties which would require handling them within one single renderer.

How would I go about validating each property in case I needed to do something like this?

Thanks again!

Hi @adamsilva01,

Validation is handled form-wide in a central place. So what you need to do then is to access the form-wide errors store and filter the contained errors for all properties which your custom renderer is handling.

To access the form wide errors you can use useJsonForms(), e.g. const store = useJsonForms(). The errors are located in store.core.errors.