vuetify-jsonschema-form-builder
v0.3.1
Published
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
Downloads
44
Readme
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 ofvuetify-jsonschema-form
schemascontext
- an object containing additional data for generating the formpredefinedSelects
- list of predefined selects that can be chosen for the dropdown componentid
- 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:
// 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>
...