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
schemascontext
- 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 dropdownlabel
- display labelurl
- URL to fetch the values fromitemsProp
- property in the response containing the dropdown optionsitemTitle
- property of the option to use as the display labelitemKey
- 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:
{
"type": "object",
"allOf": [
{
"properties": {
"textfield1": {
"title": "Short text",
"readOnly": false,
"type": "string"
},
"textfield2": {
"title": "Short text",
"readOnly": false,
"type": "string"
}
}
}
]
}
[
{
"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 {
static settings() {
return {
type: 'customfield',
key: 'customfield',
label: 'Custom field',
xCols: 12,
required: false,
readOnly: false,
padding: {},
};
}
static get builderInfo() {
return {
title: 'Custom field',
icon: 'text_fields',
optionsTemplate: DefaultOptions,
template: DefaultField,
settings: CustomFieldComponent.settings()
};
}
constructor(component: any, options: any) {
super(component, options);
}
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 (property["x-display"] == 'custom-field') {
this.visitCustomField(property, config, parent, key);
} else {
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>
...