0.3.1 • Published 1 year ago

vuetify-jsonschema-form-builder v0.3.1

Weekly downloads
-
License
-
Repository
-
Last release
1 year ago

vuetify-jsonschema-form-builder

This library is a json schema form builder intended to be used alongside vuetify-jsonschema-form which is a form renderer. This library consists of two components, a form-builder which represents the drag and drop area displaying the current layout of the form, and form-builder-tabs which represent the available controls. Check out the Demo.

Installation

npm install vuetify-jsonschema-form-builder

Usage

<template>
    <v-app>
        <v-row>
            <v-col cols="8">
                <form-builder :schema.sync="schema" :context="context"></form-builder>
            </v-col>
            <v-col cols="4">
                <form-builder-tabs :schema.sync="schema" :context="context"></form-builder-tabs>
            </v-col>
        </v-row>
    </v-app>
</template>

<script lang="ts">
import Vue from 'vue';
import { FormBuilder, FormBuilderTabs } from 'vuetify-jsonschema-form-builder';
import 'vuetify/dist/vuetify.min.css';

export default Vue.extend({
  name: "App",
  components: {
    FormBuilder, FormBuilderTabs
  },
  data() {
    return {
      schema: {
        type: 'object',
        properties: {
          stringProp: {
            type: 'string'
          },
          colorProp: {
            type: 'string',
            'x-display': 'color-picker'
          },
        }
      },
      context: {
        predefinedSelects: [
          {
            id: 'pokemon',
            label: 'Pokemon',
            url: 'https://pokeapi.co/api/v2/pokemon',
            itemsProp: 'results',
            itemTitle: 'name',
            itemKey: 'name',
          },
          {
            id: 'users',
            label: 'Users',
            url: 'https://gorest.co.in/public/v2/users',
            itemTitle: 'name',
            itemKey: 'id'
          }
        ]
      }
    };
  },
});
</script>

Props

  • schema - a jsonschema in the format of vuetify-jsonschema-form schemas
  • context - an object containing additional data for generating the form
    • predefinedSelects - list of predefined selects that can be chosen for the dropdown component
      • id - unique ID of the predefined dropdown
      • label - display label
      • url - URL to fetch the values from
      • itemsProp - property in the response containing the dropdown options
      • itemTitle - property of the option to use as the display label
      • itemKey - property of the option to use as the display value

How it works

vuetify-jsonschema-form-builder internally uses a different data structure than JSON Schema and vuetify-jsonschema-form. It works by converting a JSON Schema into this structure (which is easier to work with when editing form) using SchemaParser. Then, when the form is edited, using SchemaBuilder, converts it back into JSON schema that can be used with vuetify-jsonschema-form. This is important to know when building custom components.

Eg. a section containing two text fields:

// JSON schema
{
  "type": "object",
  "allOf": [
    {
      "properties": {
        "textfield1": {
          "title": "Short text",
          "readOnly": false,
          "type": "string"
        },
        "textfield2": {
          "title": "Short text",
          "readOnly": false,
          "type": "string"
        }
      }
    }
  ]
}

// form structure
[
  {
    "type": "panel",
    "xCols": 12,
    "components": [
      {
        "type": "textfield",
        "key": "textfield1",
        "label": "Short text",
        "readOnly": false,
      },
      {
        "type": "textfield",
        "key": "textfield2",
        "label": "Short text",
        "readOnly": false,
      }
    ]
  }
]

To know more about the form structure check the test suites for SchemaParser.

Building custom components

To start, a component definition class is needed:

./customfield/customfield.ts

export class CustomFieldComponent extends Component {

    // default settings for the component
    // used by the form builder to create and edit the component
    // can contain any number of parameters
    static settings() {
        return {
            /** type of the component, must be unique for each component type */
            type: 'customfield',
            /** key, used by the input components as the JSON property name */
            key: 'customfield',
            label: 'Custom field',
            xCols: 12,
            required: false,
            readOnly: false,
            padding: {},
        };
    }

    // info for the builder
    static get builderInfo() {
        return {
            /** title shown in the component sidebar */
            title: 'Custom field',
            /** icon shown for the component in the builder */
            icon: 'text_fields',
            /** Vue component that displays the available options for the component (sidebar) */
            optionsTemplate: DefaultOptions,
            /** Vue component rendered in the builder body as the component */
            template: DefaultField,
            /** default settings applied to the form when dragging the component */
            settings: CustomFieldComponent.settings()
        };
    }

    constructor(component: any, options: any) {
        super(component, options);
    }

    // tells the builder how to build the JSON Schema for this component
    buildSchema(parentSchema: JsonSchema) {
        parentSchema.properties[this.component.key] = {
            ...this.buildDefaultProps(),
            type: 'string',
            'x-display': 'custom-field',
        };
        parentSchema['x-cols'] = +this.component.xCols;
        this.buildRequiredProp(parentSchema);
        this.buildPadding(parentSchema.properties[this.component.key]);
    }

}

This handles the building of a form with the new component.

What remains is telling vuetify-jsonschema-form-builder how to parse JSON schemas into the format used internally by the builder for this new component, so that existing JSON schema form definitions would display this component when opened with the form builder.

This is done by defining an extension for the SchemaParser:

./components/customfield.parser.ts

 export function parseCustomField(Parser: typeof SchemaParser): typeof SchemaParser {
    return class extends Parser {
        visitStringProperty(property: JsonSchema, config: ISettings[], parent: JsonSchema, key: string): void {
            // if JSON Schema 'x-display' is 'custom-field' then it is a customfield component
            if (property["x-display"] == 'custom-field') {
                this.visitCustomField(property, config, parent, key);
            } else {
                // otherwise it is some other component
                super.visitStringProperty(property, config, parent, key);
            }
        }

        visitCustomField(property: JsonSchema, config: ISettings[], parent: JsonSchema, key: string) {
            const component = this.buildInputComponent(property, parent, key);
            component.type = 'customfield';
            config.push(component);
        }
    }
}

Be sure to check the source to see what each of methods used do.

All that is left to do is to register the component and the extension:

eg. ./App.vue

import { ComponentCache, SchemaParser } from 'vuetify-jsonschema-form-builder';
import { CustomFieldComponent } from './customfield/customfield';
import { parseCustomField } from './customfield/customfield.parser';

ComponentCache.registerComponent('customfield', CustomFieldComponent);
SchemaParser.registerExtension(parseCustomField);

Now your custom built component for vjsf can be used with the form builder. Be sure to pass your custom component template to v-jsf when rendering the built schema:

...
<v-jsf v-model="model" :schema="schema" :options="options">
  <template slot="custom-field" slot-scope="context">
    <v-custom-field v-bind="context"><v-custom-field>
  </template>
</v-jsf>
...
0.3.0

1 year ago

0.2.3

1 year ago

0.3.1

1 year ago

0.2.2

1 year ago

0.2.4

1 year ago

0.1.13

2 years ago

0.1.14

2 years ago

0.1.15

2 years ago

0.2.1

1 year ago

0.2.0

1 year ago

0.1.12

2 years ago

0.1.10

2 years ago

0.1.9

2 years ago

0.1.8

2 years ago

0.1.7

2 years ago

0.1.6

2 years ago

0.1.5

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago