# Vue Basic String Custom Renderer

**URL:** <https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280>\
**Category:** General\
**Created:** [January 31, 2023, 9:01am UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280 "2023-01-31T09:01:38Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![adamsilva01](https://avatars.discourse-cdn.com/v4/letter/a/a9adbd/32.png) [@adamsilva01](https://jsonforms.discourse.group/u/adamsilva01)\
**Post date:** [January 31, 2023, 9:01am UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/1 "2023-01-31T09:01:38Z")

</div>

So I’m starting out with Vue JSONForms and I’m trying to create a bare-bones custom text renderer. I know JSONForms has the `vue-vanilla` package, but I want to understand what are the basics needed for a custom renderer because later on I will need to do much more customization to each custom renderer I create. Here is what I have so far:

```auto
<template>
    <v-input />
</template>

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

const renderersText = defineComponent({
    name: 'renderers-text',
    setup (props: RendererProps<ControlElement>) {
        return useJsonFormsControl(props)
    },
})

export default renderersText

export const entry: JsonFormsRendererRegistryEntry = {
    renderer: renderersText,
    tester: rankWith(1, isStringControl),
}
</script>

```

But I’m getting a `r.tester is not a function` error. Any idea what this means and/or what I need to fix? Thanks in advance!

---

<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:** [January 31, 2023, 9:54am UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/2 "2023-01-31T09:54:25Z")

</div>

Hi @adamsilva01,

The code looks fine on a first glance. As the error message is related to the `tester`: Can you show how you are registering this custom renderer?

---

<div class="post-metadata">

**Author:** ![adamsilva01](https://avatars.discourse-cdn.com/v4/letter/a/a9adbd/32.png) [@adamsilva01](https://jsonforms.discourse.group/u/adamsilva01)\
**Post date:** [January 31, 2023, 10:09am UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/3 "2023-01-31T10:09:37Z")

</div>

Hey @sdirix ,

```auto
import RenderersText from '~/components/renderers/text/RenderersText.vue'
const renderers: any[] = [
    RenderersText,
]

```

---

<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:** [January 31, 2023, 10:24am UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/4 "2023-01-31T10:24:56Z")

</div>

Hi @adamsilva01,

The `renderers` are an array of `{ renderer, tester }` pairs. As you only hand over the `renderer` itself instead of an object containing the `renderer` and `tester`, JSON Forms can’t find the `tester`.

Note also that a renderer set which ONLY consists of the `RenderersText` renderer will likely also fail as JSON Forms by default auto generates a `VerticalLayout` UI Schema element for a JSON Schema object. So you should also at least add a layout renderer. See [this very related question](https://jsonforms.discourse.group/t/no-applicable-renderer-found-react-without-material/1277/2).

So instead of the renderer you should import the `entry`. If you are using the types of JSON Forms it should already complain when using the wrong one.

```auto
import { entry as renderersTextEntry } from '~/components/renderers/text/RenderersText.vue';
import { JsonFormsRendererRegistryEntry } from '@jsonforms/core';

const renderers: JsonFormsRendererRegistryEntry[] = [
  renderersTextEntry,
  // add your layout renderer entry here
]

```

In case you are struggling to export the `entry` from the `.vue` file: You need to modify the [TS module declaration for Vue to declare that `entry` is also exported](https://github.com/eclipsesource/jsonforms/blob/1b22f55dce2150c29999ad1fb220fc866023a6a0/packages/vue/vue-vanilla/shims-vue.d.ts#L6). Alternatively you could just define the `entry` outside of the `.vue` SFC.

---

<div class="post-metadata">

**Author:** ![adamsilva01](https://avatars.discourse-cdn.com/v4/letter/a/a9adbd/32.png) [@adamsilva01](https://jsonforms.discourse.group/u/adamsilva01)\
**Post date:** [January 31, 2023, 11:12am UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/5 "2023-01-31T11:12:49Z")

</div>

Hey @sdirix ,

Thanks for the detailed answer!  
I added the `vue-vanilla` package which contains some layouts, and I’ve modified the code to:

```auto
import { vanillaRenderers } from '@jsonforms/vue-vanilla'
import { entry as renderersTextEntry } from '~/components/renderers/text/RenderersText.vue'
const renderers: any[] = [
    renderersTextEntry,
    ...vanillaRenderers,
]

```

However, now I’m getting the following error: `Cannot read properties of undefined (reading 'rule')`

---

<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:** [January 31, 2023, 2:36pm UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/6 "2023-01-31T14:36:26Z")

</div>

Can you show how you invoke JSON Forms and what exactly the content of the handed over arguments is?

Unrelated to the error: Your tester needs to return a higher priority so it can reliably win against the `vanillaRenderer`

---

<div class="post-metadata">

**Author:** ![adamsilva01](https://avatars.discourse-cdn.com/v4/letter/a/a9adbd/32.png) [@adamsilva01](https://jsonforms.discourse.group/u/adamsilva01)\
**Post date:** [January 31, 2023, 2:49pm UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/7 "2023-01-31T14:49:22Z")

</div>

Hey @sdirix ,

Sure, here is the full component meant to display the form:

```auto
<template>
    <h1>JSON Forms Vue 3</h1>
    <div class="myform">
        <json-forms
            :data="data"
            :renderers="renderers"
            :schema="schema"
            :uischema="uischema"
            @change="onChange" />
    </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { JsonForms, JsonFormsChangeEvent } from '@jsonforms/vue'
import { vanillaRenderers } from '@jsonforms/vue-vanilla'
import { entry as renderersTextEntry } from '~/components/renderers/text/RenderersText.vue'
const renderers: any[] = [
    renderersTextEntry,
    ...vanillaRenderers,
]

const schema = {
    properties: {
        name: {
            type: 'string',
            minLength: 1,
            description: "The task's name",
        },
        description: {
            title: 'Long Description',
            type: 'string',
        },
    },
}
const uischema = {
    type: 'HorizontalLayout',
    elements: [
        {
            type: 'VerticalLayout',
            elements: [
                {
                    type: 'Control',
                    scope: '#/properties/name',
                },
                {
                    type: 'Control',
                    scope: '#/properties/description',
                    options: {
                        multi: true,
                    },
                },
            ],
        },
    ],
}
export default defineComponent({
    name: 'app',
    components: { JsonForms },
    data () {
        return {
            // freeze renderers for performance gains
            renderers: Object.freeze(renderers),
            data: {
                name: 'Send email to Adrian',
                description: 'Confirm if you have passed the subject\nHereby ...',
            },
            schema,
            uischema,
        }
    },
    methods: {
        onChange (event: JsonFormsChangeEvent) {
            this.data = event.data
        },
    },
})
</script>

```

---

<div class="post-metadata">

**Author:** ![adamsilva01](https://avatars.discourse-cdn.com/v4/letter/a/a9adbd/32.png) [@adamsilva01](https://jsonforms.discourse.group/u/adamsilva01)\
**Post date:** [February 7, 2023, 2:02pm UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/8 "2023-02-07T14:02:36Z")

</div>

Hey @sdirix ,

Eventually the issue was solved since I added the following to the component:

```auto
props: {
    ...rendererProps<ControlElement>(),
},

```

However, now I’m getting a warning from the console with the following:

```auto
[Vue warn]: Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw or usi
ng shallowRef instead of ref.
Component that was made reactive: {
  name: 'render-text',
  props: {
    schema: { required: true, type: [Array] },
    uischema: { required: true, type: [Function: Object] },
    path: { required: true, type: [Function: String] },
    enabled: { required: false, type: [Function: Boolean], default: undefined },
    renderers: { required: false, type: [Function: Array], default: undefined },
    cells: { required: false, type: [Function: Array], default: undefined },
    config: { required: false, type: [Function: Object], default: undefined }
  },
  setup: [Function (anonymous)],
  ssrRender: [Function: _sfc_ssrRender],
}

```

Any idea on how to fix this? Should I manually declare the props that I need instead of using `rendererProps`?

---

<div class="post-metadata">

**Author:** ![adamsilva01](https://avatars.discourse-cdn.com/v4/letter/a/a9adbd/32.png) [@adamsilva01](https://jsonforms.discourse.group/u/adamsilva01)\
**Post date:** [February 8, 2023, 2:04pm UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/9 "2023-02-08T14:04:41Z")

</div>

I fixed the issue by adding `markRaw` to the renderers array, since this will make it so the components are not reactive and avoid getting the Proxy wrapped around them

---

<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:** [February 9, 2023, 8:04pm UTC](https://jsonforms.discourse.group/t/vue-basic-string-custom-renderer/1280/10 "2023-02-09T20:04:07Z")

</div>

Hi @adamsilva01,

Great that you found a solution!

> Eventually the issue was solved since I added the following to the component […]

Ah I see the error was a Typescript problem! I thought this is about a runtime problem…

> I fixed the issue by adding `markRaw` to the renderers array, since this will make it so the components are not reactive and avoid getting the Proxy wrapped around them

In our seed apps and package readmes we use `Object.freeze`.
