Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example for Custom Renderer #13

Open
bishopandco opened this issue Jul 25, 2022 · 8 comments
Open

Example for Custom Renderer #13

bishopandco opened this issue Jul 25, 2022 · 8 comments

Comments

@bishopandco
Copy link

It would be very helpful if this seed project showed how to add a custom renderer.

@bishopandco
Copy link
Author

bishopandco commented Aug 30, 2022

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>

@bart-jaskulski
Copy link

bart-jaskulski commented Sep 1, 2022

@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.

@sdirix
Copy link
Member

sdirix commented Sep 1, 2022

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 👍

Note that redefining the renderer entry within the index.ts is not necessary. You can just add it to the list directly.

@bishopandco
Copy link
Author

@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!

@bart-jaskulski
Copy link

@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.

@sdirix
Copy link
Member

sdirix commented Sep 2, 2022

In the Readmes we suggest using Object.freeze on the whole renderer set. Is that not sufficient?

@bart-jaskulski
Copy link

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.

@sdirix
Copy link
Member

sdirix commented Sep 2, 2022

That's a good idea. If you like you can contribute the FAQ question here: https://github.com/eclipsesource/jsonforms2-website

mgineer85 added a commit to photobooth-app/photobooth-frontend that referenced this issue Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants