Vue + ElementUI implements form dynamic rendering and visualized configuration. vueelementui

Source: Internet
Author: User

Vue + ElementUI implements form dynamic rendering and visualized configuration. vueelementui

Dynamic rendering is an asynchronous data, which is about long:

{"Inline": true, "labelPosition": "right", "labelWidth": "", "size": "small", "statusIcon": true, "formItemList ": [{"type": "input", "label": "name", "disable": false, "readonly": false, "value ":"", "placeholder": "Enter name", "rules": [], "key": "name", "subtype": "text" },{ "type ": "radio", "label": "gender", "value": "", "button": false, "border": true, "rules": [], "key": "gender", "options": [{"value": "1", "label": "male", "disabled": false }, {"value": "0", "label": "female", "disabled": false}]}

Then you need to render the json as follows:

 

The Data Length of the final submitted form is as follows:

{ "name": "Genji", "gender": "1"}

Then our goal is to encapsulate such a component:

<dynamic-form :config="someConfig" v-model="someData" />

Implementation

Before starting, You Need To Know How v-model works:

<input v-model="something">

This is just the syntax sugar in the following example:

<input :value="something" @input="something = $event.target.value">

After learning about this, let's implement this component step by step.

First, forward the configuration to el-form:

<template> <el-form  class="dynamic-form"  :inline="formConfig.inline"  :model="value"  :label-position="formConfig.labelPosition"  :label-width="formConfig.labelWidth"  :size='formConfig.size'  :status-icon="formConfig.statusIcon"> <slot/> </el-form></template><script>export default { props: { formConfig: { type: Object, required: true }, value: { type: Object, required: true } },}</script>

Step 2: Set the default value.

Because in each form-item A v-model is required, so before rendering, ensure that each field has a value. Note that do not directly modify the prop passed by the parent component in the component, so we use {...this.value} Copy a copy quickly. Do not forget to notify the parent component. The Code is as follows:

Export default {props: {formConfig :{...}, value :{...},}, methods: {setDefaultValue () {const formData = {... this. value} // set the default value this. formConfig. formItemList. forEach ({key, value}) ==>{ if (formData [key] === undefined | formData [key] === null) {formData [key] = value}) this. $ emit ('input', formData) }}, mounted () {this. setDefaultValue ()},}

Step 3: render form-item.

How can we render the following data as a familiar el-form-item?

{"Type": "input", "label": "name", "disable": false, "readonly": false, "value": "", "placeholder ": "Enter name", "rules": [], "key": "name", "subtype": "text "}

First, the built-in component of vue may be written as follows:

<el-form-item> <component :is="`el-${item.type}`" /></el-form-item>

Second, use v-if to judge one by one:

<El-form-item> <el-input v-if = "item. type = 'input' "/> <span v-else> unknown control type </span> </el-form-item>

Considering that the processing logic of each form control varies widely, the author adopted the second method.

According to this idea, we encapsulatedynamic-form-item , Receives an item and renders an el-form-item:

<Template> <el-form-item: rules = "item. rules ": label =" item. label ": prop =" item. key "> <el-input v-if =" item. type = 'input' "v-bind =" $ attrs "v-on =" $ listeners ": type =" item. subtype ": placeholder =" item. placeholder ": disabled =" item. disable ": readonly =" item. readonly ": autosize =" item. autosize "> </el-input> <el-select v-else-if =" item. type = 'select' "v-bind =" $ attrs "v-on =" $ listeners ": multiple =" item. multiple ": Disabled = "item. disabled ": multiple-limit =" item. multipleLimit "> <el-option v-for =" o in item. options ": key =" o. value ": label =" o. label ": value =" o. value ": disabled =" o. disabled "> </el-option> </el-select> <! -- Suddenly miss JSX -->... <span v-else> unknown control type </span> </el-form-item> </template> <script> export default {props: {item: {type: object, required: true }}</script>

Tips: Used v-bind="$attrs" v-on="$listeners" You can easily forward v-model Command. For more information, see vue advanced components.

Finally, we can output a complete form cyclically:

<dynamic-form-item v-for="item in formConfig.formItemList" :key="item.key" v-if="value[item.key]!==undefined" :item="item" :value="value[item.key]" @input="handleInput($event, item.key)" />

Not available herev-model="value[item.key]" As mentioned above, the props cannot be directly modified in the component, so we will forward it here.

Methods: {handleInput (val, key) {// here, element-ui does not report the event, and this is the value. $ emit ('input ',{... this. value, [key]: val})}, setDefaultValue (){...}},

Complete Code address:src/components/dynamic-form/form.vue

Extended Functions

1. Number Display Unit, limited to decimal places

Element-ui does not do this function, but I think it is quite common, so using el-input to manually encapsulate an input-number:

 

<! -- Common usage --> <input-number v-model = "someNumber": min = "1": max = "99 ": decimal1 = "2" append = ""> </input-number> <! -- Application in dynamic-form-item --> <input-number v-else-if = "item. type = 'number' "v-bind =" $ attrs "v-on =" $ listeners ": min =" item. min ": max =" item. max ": decimal1 =" item. decimal1 ": append =" item. append ": prepend =" item. prepend ": disabled =" item. disabled "> </input-number>

Complete code:src/components/dynamic-form/input-number.vue

2. asynchronous Verification

Thanks to async-validator, we can easily customize verification rules.

 

In configuration

{"Type": "input ",... "rules": [{"SQL": "SELECT {key} FROM balabala", "message": "xx occupied", "trigger": "blur"}]}

In dynamic-form-item In the component, traverse item. rules and convert SQL verification to a custom validator function:

<Template> <el-form-item: rules = "Rules">... </el-form-item> </template> <script> import request from '@/utils/request' export default {props: {item :{...}}, computed: {Rules () {const rules = this. item. rules if (rules = undefined) return undefined const R = [] rules. forEach (rule => {if (rule. SQL) {const validator = (rule2, value, callback) => {// modify the request ('/api/validate', 'post', {k Ey: rule2.field, value, SQL: rule. SQL. replace (/{key}/ig, rule2.field)}). then (res => {callback (! Res | undefined )}). catch (err => {this. $ message. error (err. message) callback (false)} R. push ({validator, message: rule. message, trigger: 'blur'})} else {R. push (rule) }}) return R }},}</script>

3. Fast configuration of provincial and municipal areas

Thanks to the author of element-china-area-data.

In Configuration:

{ "type": "cascader", ... "areaShortcut": "provinceAndCityData"}

In the dynamic-form-item component:

<template> <el-form-item>  ...  <el-cascader    :options="item.options || require('element-china-area-data')[item.areaShortcut]"   ></el-cascader> </el-form-item></template>

4. Remote Loading options

Including but not limited to radio, checkbox, cascader, select

In Configuration:

{ "type": "checkbox", ... "optionsUrl": "/api/some/options"}

In the dynamic-form-item component:

<Template> <el-form-item>... <el-select> <el-option v-for = "o in item. options | ajaxOptions "> </el-option> </el-select> </el-form-item> </template> <script> import request from '@/utils /request 'export default {props: {item :{...}}, computed :{...}, data () {return {ajaxOptions: [] }}, created () {const {optionsUrl, key, type} = this. item if (optionsUrl) {// modify the request ('$ {optionsUrl }? Key =$ {key} ', 'get '). then (res => {this. ajaxOptions = res }). catch (err => {this. $ message. error (err. message)}) }}</script>

Summary

The above section describes how to use Vue + ElementUI to implement dynamic form rendering and visualized configuration. I hope it will help you. If you have any questions, please leave a message, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.