jsonforms-vue-seed
jsonforms-vue-seed copied to clipboard
Example for Custom Renderer
It would be very helpful if this seed project showed how to add a custom renderer.
First: Create a folder for you renderers. Add an index.ts
import { entry as CustomRenderer } from "@/renderers";
export const CustomRenderers: unknown[] = [
{
renderer: CustomRenderer.renderer,
tester: CustomRenderer.tester
}
];
export default CustomRenderers;
Create CustomRenderer.vue
<script lang="ts">
import { isLayout, and, uiTypeIs, rankWith } from "@jsonforms/core";
import type { JsonFormsRendererRegistryEntry, Layout } from "@jsonforms/core";
import { defineComponent } from "vue";
import {
DispatchRenderer,
rendererProps,
useJsonFormsLayout,
} from "@jsonforms/vue";
const CustomRenderer = defineComponent({
name: "block-layout-renderer",
components: {
DispatchRenderer,
},
props: {
...rendererProps<Layout>(),
},
setup(props) {
return useJsonFormsLayout(props);
},
});
export default CustomRenderer;
export const entry: JsonFormsRendererRegistryEntry = {
renderer: CustomRenderer,
tester: rankWith(3, and(isLayout, uiTypeIs("BlockLayout"))),
};
</script>
<template>
<div>
<div
v-for="(element, index) in layout.uischema.elements"
v-bind:key="`${layout.path}-${index}`"
>
<dispatch-renderer
v-bind:schema="layout.schema"
v-bind:uischema="element"
v-bind:path="layout.path"
v-bind:enabled="layout.enabled"
v-bind:renderers="layout.renderers"
v-bind:cells="layout.cells"
/>
</div>
</div>
</template>
Import the Custom Renderers and the vanilla renderers.
<template>
<json-forms
:data="fooBar"
:renderers="renderers"
:schema="schema"
:uischema="uiSchema"
@change="onChange"
/>
</template>
<script lang="ts">
import { JsonForms } from "@jsonforms/vue";
import { vanillaRenderers } from "@jsonforms/vue-vanilla";
import type { JsonFormsRendererRegistryEntry } from "@jsonforms/core";
import type { JsonSchema7 } from "@jsonforms/core";
import { CustomRenderers } from "@/renderers";
const renderers: JsonFormsRendererRegistryEntry[] = [
...customRenderers,
...vanillaRenderers,
];
export default {
components: { JsonForms },
props: {
fooBar: Object,
schema: Object as JsonSchema7,
uiSchema: Object,
onChange: Function,
},
setup() {
return { renderers };
},
};
</script>
@bishopandco following your response on issue eclipsesource/jsonforms#1744 I would like to add example of SFC component with <script setup> for registering renderers.
<script lang="ts" setup>
import type {ControlElement,} from "@jsonforms/core";
import ControlWrapper from './ControlWrapper.vue';
import {rendererProps, useJsonFormsControl,} from "@jsonforms/vue";
import {useVanillaControl} from "../util";
const props = defineProps(rendererProps<ControlElement>())
const { control, controlWrapper, onChange, styles, isFocused, appliedOptions } = useVanillaControl(useJsonFormsControl(props))
</script>
<template>
<control-wrapper
v-bind="controlWrapper"
:styles="styles"
:isFocused="isFocused"
:appliedOptions="appliedOptions"
>
<input
:id="control.id + '-input'"
:class="styles.control.input"
:value="control.data"
:disabled="!control.enabled"
:autofocus="appliedOptions.focus"
:placeholder="appliedOptions.placeholder"
@change="onChange"
@focus="isFocused = true"
@blur="isFocused = false"
/>
</control-wrapper>
</template>
Then, you register if from scratch in another file.
index.ts (ommited import section)
export const renderers = [
{
renderer: StringControlRenderer,
tester: rankWith(1, isStringControl)
}
]
Additionally, I would suggest to markRaw components you register as renderer because Vue complains about possible performance issues when passing reactive components.
Hi @bishopandco,
It definitely makes sense to add an example custom renderer to the Vue seed, similar to the React seed. If you like you can contribute your custom renderer(s) to the main and vue2 branches :+1:
Note that redefining the renderer entry within the index.ts is not necessary. You can just add it to the list directly.
@bart-jaskulski Awesome! I've been chasing the markRaw warning for a while. Can't find the right place to do that. Any tips there?
@sdirix will try to soon!
@bishopandco I do during registration, just like:
{
renderer: markRaw(StringControlRenderer),
tester: rankWith(1, isStringControl)
}
For what I know, it doesn't cause any issues about rendering fields.
In the Readmes we suggest using Object.freeze on the whole renderer set. Is that not sufficient?
Thank you @sdirix, it actually does help! I didn't notice that vue-vanilla repository uses renderers in this way in readme section. I think such information could go to some FAQ section in documentation, wherever it will be more exposed.
That's a good idea. If you like you can contribute the FAQ question here: https://github.com/eclipsesource/jsonforms2-website