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

Plugin creation #433

Open
boutils opened this issue Apr 18, 2024 · 4 comments
Open

Plugin creation #433

boutils opened this issue Apr 18, 2024 · 4 comments

Comments

@boutils
Copy link

boutils commented Apr 18, 2024

Hello, I am trying to create a plugin with a specific control I would like to use.
Can you tell me if plugins are already supported? I followed the way markdown is done, but as soon as I tried to use my plugin, I hit some errors due to schema validation.

Screenshot 2024-04-18 at 04 12 11

The plugin is setup this way:

<template>
  <div
    class = "stoic-form"
    :id   = "identifier">
    <v-container>
      <v-row>
        <v-col>
          <v-form>
            <vjsf
              v-model  = "data"
              :schema  = "schema"
              :options = "options">
            </vjsf>
          </v-form>
        </v-col>
      </v-row>
    </v-container>
  </div>
</template>

<script>
  import Vjsf from '@koumoul/vjsf';
  import myPlugin from '../components/my-plugin/my-plugin.vue';

  export default {
    name: 'stoicForm',

    components: { Vjsf },

    data() {
      return {
        data: {},
        options: {
          nodeComponents: { myplugin: myPlugin },
        },
        schema: {
          type: 'object',
          properties: {
            str1: {
              type: 'string',
              title: 'My plugin control',
              layout: 'myplugin',
            },
          },
        },
      };
    },
  };
</script>

I can see in the json-layout repository that markdown is hardcoded in several places. Is it already ready to work with user-made plugins?

If I omit the validation in json-layout/normalize.js, I can see my plugin/component. I set as comment the 2 validation blocks in function normalizeLayoutFragment:

/* json-layout/vocabulary/src/normalize.js */

...
export function normalizeLayoutFragment (schemaFragment, schemaPath, markdown = (src) => src, optionsKeys, arrayChild) {
  optionsKeys = optionsKeys ? optionsKeys.concat(defaultOptionsKeys) : defaultOptionsKeys
  let layoutKeyword
  if (arrayChild === 'oneOf') {
    layoutKeyword = schemaFragment.oneOfLayout ?? {}
  } else {
    layoutKeyword = schemaFragment.layout ?? {}
  }
  // if (!validateLayoutKeyword(layoutKeyword)) {
  //   console.error(`layout keyword validation errors at path ${schemaPath}`, layoutKeyword, validateLayoutKeyword.errors)
  //   return {
  //     layout: getNormalizedLayout({}, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild).normalized,
  //     errors: lighterValidationErrors(validateLayoutKeyword.errors)
  //   }
  // }
  const normalizedLayout = getNormalizedLayout(layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild)
  // if (!validateNormalizedLayout(normalizedLayout.normalized)) {
  //   console.error(`normalized layout validation errors at path ${schemaPath}`, normalizedLayout, validateNormalizedLayout.errors)
  //   return {
  //     layout: getNormalizedLayout({}, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild).normalized,
  //     errors: lighterValidationErrors(validateNormalizedLayout.errors)
  //   }
  //   // throw new Error(`invalid layout at path ${schemaPath}`, { cause: validateNormalizedLayout.errors })
  // }
  return { layout: normalizedLayout.normalized, errors: [] }
}

@albanm Do you have any input? Can you please provide some guidance?
Thank you very much !

@albanm
Copy link
Member

albanm commented Apr 18, 2024

Yes, this is a good question for which my answer is not very clear I am afraid.

The way we build and validate the vocabulary is not very extensible. We could allow for unknown values of "comp", but then what would the associated properties be ? Does this custom node component accept a label, is it focusable, etc ? So I would have to accept basically anything in the layout keyword to allow for custom behavior and validation would become very lax (along with the type checking that comes with the validation and helps writing a safe code base).

So yeah, maybe things will move on this topic, I need to think about it more. But for now the situation is:

  • plugins are mostly considered as optional but standard parts of the library, they map with known elements of the vocabulary
  • they are useful to prevent pulling all dependencies always and to allow for concurrent implementations of components when there is not a single obvious possible implementation
  • for truly custom behavior use slots

@boutils
Copy link
Author

boutils commented Apr 18, 2024

Thank you for your answer @albanm. It makes sense.
I think plugins should have the same model as standard Vuetify form components, they have label, hint, ... are focusable and accept some other various props props: {...}. The JSON definition of a custom "layout/comp" should have the same API.

Of course, depending of the plugin, we can give specific options like you did for markdown:

const vjsfOptions = {
  ...
  plugins: {
    markdown: {
      easyMDEOptions: { minHeight: '300px', maxHeight: '300px' }
    }
  }
}

My guess is we should have a register mechanism for our plugins that help go through json-layout/normalizeLayoutFragment validation.

Your suggestion to use a slot doesn't work well IMHO for "like Vuetify" components but I would be very happy to discuss it. The JSON will be very complex and not really reusable.

I hope to be able to present an example in the coming days of such a plugin which make a ton of sense for me.

@albanm
Copy link
Member

albanm commented May 2, 2024

I reworked the plugin mechanism both at the json-layout level (vocabulary is now extensible) and vjsf.

The markdown plugin was updated accordingly and the doc too.

@boutils
Copy link
Author

boutils commented May 2, 2024

Thanks a ton @albanm, you rock!

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

2 participants