# Getting Started

Warm Prompt

vue-dynamic-form-component should use with Vue (opens new window) and element-ui (opens new window), please install them first.

# Installation

# CDN

Get the latest version from unpkg.com/vue-dynamic-form-component (opens new window), and import the javascript file in your page.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <!-- import CSS -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
  <div id="app">
    <dynamic-form v-model="data" :descriptors="descriptors"></dynamic-form>
  </div>
</body>
  <!-- import Vue and ElementUI before vue-dynamic-from-component -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <!-- import JavaScript -->
  <script src="https://unpkg.com/vue-dynamic-form-component/lib/vue-dynamic-form-component.umd.min.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: function () {
        return {
          data: {},
          descriptors: {
            string: { type: 'string', required: true }
          }
        }
      }
    })
  </script>
</html>

# NPM

Installing with npm is recommended and it works seamlessly with webpack (opens new window).

# yarn
yarn add vue-dynamic-form-component
# or npm
npm install vue-dynamic-form-component

# Registration

# Global Registered

import Vue from 'Vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

import DynamicForm from 'vue-dynamic-form-component'
Vue.use(DynamicForm)

# Registered in Component

Warm Prompt

Don't forget to register the element-ui (opens new window) first.

<script>
import DynamicForm from 'vue-dynamic-form-component'
export default {
  components: {
    DynamicForm
  }
}
</script>

# Usage

# Simple Data Type

The component support common data type:string, number, boolean, integer, float, enum, date, url, hex, email and so on, more type reference to descriptor.type

Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        date: { type: 'date', label: 'date\'s label', required: false },
        number: { type: 'number', label: 'number\'s label', required: true, props: { placeholder: 'please input the number' } },
        string: { type: 'string', label: 'string\'s label', required: true, pattern: /^test$/g },
        url: { type: 'url', label: 'url\'s label', required: true, props: { placeholder: 'please input the url' } },
        email: { type: 'email', label: 'email\'s label', required: false },
        enum: {
          type: 'enum',
          label: 'enum\'s label',
          enum: ['value-1', 'value-2'],
          options: [
            { label: 'option-1', value: 'value-1', disabled: true },
            { label: 'option-2', value: 'value-2' }
          ]
        }
      },
      data: {}
    }
  }
}
</script>

# Object

To generate Object, use type: 'object' with fields

Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        object: {
          type: 'object',
          label: 'Normal Object',
          fields: {
            object: {
              type: 'object',
              label: 'Child Object',
              fields: {
                boolean: { type: 'boolean', required: true },
                number: { type: 'number', required: true },
                string: { type: 'string', required: true, pattern: /^test$/g }
              }
            },
            boolean: { type: 'boolean', required: true },
            number: { type: 'number', required: true },
            string: { type: 'string', required: true, pattern: /^test$/g }
          }
        }
      },
      data: {}
    }
  }
}
</script>

# Hashmap

To generate Hashmap, use type: 'object' with defaultField

Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        hashmap: {
          type: 'object',
          label: 'hashmap Object',
          defaultField: {
            type: 'object',
            fields: {
              boolean: { type: 'boolean', required: true },
              number: { type: 'number', required: true },
              string: { type: 'string', required: true, pattern: /^test$/g }
            }
          }
        }
      },
      data: {}
    }
  }
}
</script>

# Array

To generate Array, use type: 'array' with defaultField. If the array items are enumerable, you can use type: 'enum' in defaultField with multiple: true. It will generate a multi-select component.

Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        array: {
          type: 'array',
          label: 'array label',
          defaultField: {
            type: 'object',
            fields: {
              boolean: { type: 'boolean', required: true },
              string: { type: 'string', required: true, pattern: /^test$/g },
              array: {
                type: 'array',
                defaultField: {
                  type: 'object',
                  fields: {
                    boolean: { type: 'boolean', required: true },
                    string: { type: 'string', required: true, pattern: /^test$/g }
                  }
                }
              }
            }
          }
        },
        multiSelect: {
          type: 'array',
          label: 'multi-select',
          required: true,
          defaultField: {
            type: 'enum',
            multiple: true,
            enum: [0, 1, 2, 3],
            options: [
              { label: 'option-0', value: 0, disabled: true },
              { label: 'option-1', value: 1 },
              { label: 'option-2', value: 2 },
              { label: 'option-3', value: 3 }
            ]
          }
        }
      },
      data: {}
    }
  }
}
</script>

# Custom Validation

Generally, you don't need to write extra code for field's validation. vue-dynamic-form-component provides default validate rule and message base on type

If you need to custom the validate rule or message, you can use the following methods

# Custom Validate Message

You can cover the default validate message by adding the message prop. You can add multi rule for one field by using Array.

Warning

Special prop label, fields, defaultField , ...etc should be used with type in one rule. Reference to descriptor.type

Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        string: { type: 'string', label: 'username', required: true, message: 'Input the username please' },
        url: [
          { type: 'url', label: 'homepage', message: 'Homepage must be a url' },
          { required: true, message: 'Homepage is required' }
        ],
        test: { type: 'string', whitespace: true }
      },
      data: {}
    }
  }
}
</script>

# Custom Validator

vue-dynamic-form-component provides many configurations to meet most of validate rules. Here are some common configurations, more configurations reference to descriptor.

Prop Type Description
required Boolean whether the prop value is required
pattern RegExp regexp to match prop value
len Number validate length of string or array
validator Function(rule, value, callback) Custom validate function, callback(Error) mean validate error, callback() mean validate success
Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        author: [
          { type: 'string', label: 'Author Name', required: true },
          {
            validator: (rule, value, callback) => {
              if (value.length <= 5) {
                callback(new Error('The author name\'s length must more than 5'))
              } else {
                callback()
              }
            }
          }
        ]
      },
      data: {}
    }
  }
}
</script>

# Custom Component

Warm Prompt

To custom component, you should ensure version >= 2.5.0

vue-dynamic-form-component has components for common data type inside, so you don't need to custom the component generally. But sometimes, we need to custom the component, such as upload a file. To meet these scenes, I provide a way to custom the component. Usage like this:

Click To Show/Hide Demo
<template>
  <dynamic-form
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        fruits: {
          type: 'string',
          message: 'choose your favorate fruit',
          component: {
            name: 'el-radio-group',
            props: {
              fill: 'red'
            },
            events: {
              change: (data) => {
                window.alert(`you choose the ${data}`);
              }
            },
            children: [
              {
                name: 'el-radio-button',
                props: {
                  label: 'apple'
                }
              },
              {
                name: 'el-radio-button',
                props: {
                  label: 'banana',
                  disabled: true
                }
              }
            ]
          }
        }
      },
      data: {}
    }
  }
}
</script>

The component was writed by used v-model , so you can use the custom component directly after changing the component.name. The component structure in descriptors is:

component: {
  name: 'el-radio-group', // component's name
  props: {}, // component's props
  events: {}, // component's events
  children: [], // component or string(plain text dom)
}

# Component without v-model

If you want to use component like el-image that without v-model, you need to write a component yourself.

First, write the custom component:

<template>
  <div class="my-image">
    <el-image :src="_value"></el-image>
  </div>
</template>

<script>
export default {
  name: 'my-image',
  props: {
    value: {
      required: true
    }
  },
  computed: {
    _value: {
      get () {
        return this.value
      },
      set (value) {
        this.$emit('input', value)
      }
    }
  }
}
</script>

Then, register it global:

import MyImage from './MyImage'
Vue.component(MyImage.name, MyImage)

Finally, you can use the component like previous step.

Also, you can add more feature to you custom component, such as set to default value when the image loaded error:

<template>
  <div class="my-image">
    <el-image :src="_value" @error="error"></el-image>
  </div>
</template>

<script>
export default {
  name: 'my-image',
  props: {
    value: {
      required: true
    }
  },
  computed: {
    _value: {
      get () {
        return this.value
      },
      set (value) {
        this.$emit('input', value)
      }
    }
  },
  method: {
    error () {
      this._value = '<default-image-url>'
    }
  }
}
</script>

# Form Operations

vue-dynamic-form-component provides some common methods to operate form, you can use them with operations slot.

Warm Prompt

The document import the el-button component for convenience, you should import by yourself, if you need it in actual use. You can refer the specific parameters of form methods to Component Methods.

Click To Show/Hide Demo





 
 
 
 
 






































<template>
  <dynamic-form
    ref="dynamic-form"
    v-model="data"
    :descriptors="descriptors"
    :lang="lang">
    <template slot="operations">
      <el-button @click="clearValidate">clearValidate</el-button>
      <el-button type="primary" @click="resetFields" plain>resetFields</el-button>
      <el-button type="primary" @click="validate">validate</el-button>
    </template>
  </dynamic-form>
</template>

<script>
export default {
  props: ['lang'],
  data () {
    return {
      descriptors: {
        prop1: {
          type: 'object',
          fields: {
            prop1: { type: 'string', required: true }
          }
        },
        prop2: {
          type: 'object',
          defaultField: { type: 'string', required: true }
        }
      },
      data: {}
    }
  },
  methods: {
    clearValidate () {
      this.$refs['dynamic-form'].clearValidate()
    },
    resetFields () {
      this.$refs['dynamic-form'].resetFields()
    },
    async validate () {
      const valid = await this.$refs['dynamic-form'].validate()
      window.alert(`valid result ====> ${valid}`)
    }
  }
}
</script>
Last Updated: 10/20/2020, 6:03:15 PM