Generate forms using JSON Schema and Vue.js

vue-json-schema

If you are looking to use forms with your existing data in JSON Schema form, then you can use a Vue component which is just right for the job. vue-json-schema is a Vue component which generates forms based on given JSON Schemas.

JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.

FormSchema API

props

  • schema Object (required) The JSON Schema object. Use the v-if directive to load asynchronous schema.

  • v-model Object (optional) default: [object Object] Use this directive to create two-way data bindings with the component. It automatically picks the correct way to update the element based on the input type.

  • autocomplete String (optional) This property indicates whether the value of the control can be automatically completed by the browser. Possible values are: off and on.

  • novalidate Boolean (optional) This Boolean attribute indicates that the form is not to be validated when submitted.

  • item-class String (optional) Use this prop to enable inputs wrapping

  • data-class-error String (optional) default: 'form-error'

events

  • input undefined

  • change Fired when an form input value is changed.

  • invalid Fired when a submittable element has been checked and doesn't satisfy its constraints. The validity of submittable elements is checked before submitting their owner form.

  • submit Fired when a form is submitted

methods

  • input(name) Get a form input component

  • reset() Reset the value of all elements of the parent form.

  • submit(e) Send the content of the form to the server

  • setErrorMessage(message) Set a message error.

  • clearErrorMessage() clear the message error.

Vue JSON Schema Demo

There is a demo using the ElementUI toolkit, to show you how you can define your schema and then use it in your project to create forms with the desired functionality.

Install the component

npm install --save vue-json-schema

Define your JSON Schema file:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "title": "Newsletter Subscription",
  "description": "Sign up for free newsletters and get more delivered to your inbox",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 8,
      "maxLength": 80,
      "title": "Full Name",
      "attrs": {
        "placeholder": "Your Full Name",
        "title": "Please enter your full name"
      }
    },
    "email": {
      "type": "string",
      "maxLength": 120,
      "title": "Email",
      "attrs": {
        "type": "email",
        "placeholder": "Your Email"
      }
    },
    "lists": {
      "type": "string",
      "title": "List",
      "enum": ["Daily New", "Promotion"],
      "attrs": {
        "placeholder": "Select your list subscription"
      }
    },
    "source": {
      "type": "string",
      "maxLength": 120,
      "title": "Source",
      "description": "Ex. Using the NPM Search Engine",
      "attrs": {
        "type": "textarea",
        "placeholder": "How did you hear about us?"
      }
    },
    "agree": {
      "type": "boolean",
      "title": "Agree",
      "description": "You agree to receive occasional updates and special offers for vue-json-schema updates.",
      "default": false,
      "attrs": {
        "type": "checkbox"
      }
    }
  },
  "additionalProperties": false,
  "required": ["name", "email", "lists"]
}

In your Vue file:

<template>
  <el-card class="form">
    <form-schema ref="form"
      :schema="schema" v-model="model" @submit.prevent="submit">
      <el-button type="primary" @click="submit">Subscribe</el-button>
    </form-schema>
  </el-card>
</template>

<script>
  import FormSchema from 'vue-json-schema'
  import {
    Form,
    FormItem,
    Input,
    Radio,
    Checkbox,
    Switch,
    Select,
    Option,
    Button
  } from 'element-ui'

  FormSchema.setComponent('form', Form, (vm) => {
    // vm is the FormSchema VM

    const labelWidth = '120px'
    const model = vm.data
    const rules = {}

    vm.fields.forEach((field) => {
      rules[field.name] = {
        required: field.required,
        message: field.title
      }
    })

    return { labelWidth, rules, model }
  })

// Use `FormSchema.setComponent(type, component[, props = {}])` to define custom element to use for rendering.
  FormSchema.setComponent('label', FormItem)
  FormSchema.setComponent('email', Input)
  FormSchema.setComponent('text', Input)
  FormSchema.setComponent('textarea', Input)
  FormSchema.setComponent('checkbox', Checkbox)
  FormSchema.setComponent('checkbox', Switch)
  FormSchema.setComponent('radio', Radio)
  FormSchema.setComponent('select', Select)
  FormSchema.setComponent('option', Option)

  export default {
    data: () => ({
      schema: require('@/schema/newsletter'),
      model: {}
    }),
    methods: {
      submit (e) {
        // this.model contains the valid data according your JSON Schema.
        // You can submit your model to the server here
        console.log(JSON.stringify(this.model))
      }
    },
    components: { FormSchema }
  }
</script>

The component will assume the following structure:

This is the result of the above code, a subscription form with multiple inputs.

The project is open-source under the MIT license. See the repository for more details.