Vue.js+ElementUI+vant generate dynamic form configuration

preface

Our company is building a background management system recently, which uses Vue and element UI. When we encounter a problem and need to deal with a lot of forms, the solution we think of is to generate dynamic forms through background configuration, which is also a new challenge for me. The functions involved include dynamic form rendering and verification, So let's learn how I realized it!

This article only represents the author's own ideas. If you have a better implementation method, you can leave your valuable suggestions below. The author will be very grateful

Development preparation

Knowledge points to be reserved

  • Understanding Element ui forms
  • Understand the $set(target,key,value) method in Vue
  • Understanding form components in vant

This project is based on vue-cli2 The scaffold built by 0 is built by default here. Who agrees and who opposes!

Static form data preparation

The data returned in the background is like this. Here we take json data as an example

{
    "showName": "full name",	// name
    "showValue": null,    //value
    "htmlElements": "Input box", // form types 
    "fieldLength": 99,	// Field length
    "requiredOrNot": 1,	//	Required
}

Then there are the following types

  • Input box
  • Text field
  • calendar control
  • Drop down box
  • Radio
  • check box

We generate a component for each type, test Inside Vue assembly

data(){
    return{
        fieldArray:[],// Form field collection
        fieldObj:{},
        sex:[{    // Gender
            name:'male',
            value:"male"
        },{
            name:"female",
            value:"female"
        }
            ],
        hobbies:[ // hobby
            {
                name:"having dinner",
                value:"having dinner"
            },{
                name:"play a game",
                value:"play a game"
            },{
                name:"Beat beans",
                value:"Beat beans"
            },
        ],
        job:[{  // occupation
            name:"doctor",
            value:"doctor"
        },{
            name:"teacher",
            value:"teacher"
        },{
            name:"driver",
            value:"driver"
        }
            ]
    }
}

A variety of calendar controls are prepared here because they need to be used when using vant components on subsequent mobile phones

Because the data in vue is bidirectional bound, only the data in data can be bidirectional bound. The data added to data again cannot achieve the effect of bidirectional binding. The official website provides us with a set method.

As a pretty boy, I must have prepared the official website link for you very attentively

Official website link

There is no more explanation here. The official website is more authoritative. The focus of this blog is dynamic forms.

Vue.set(target,propertyName/index,value)

  • Parameters:

    • {Object | Array} target
    • {string | number} propertyName/index
    • {any} value
  • Return value: the value set.

Usage:

Add a property to the responsive object and ensure that the new property is also responsive and triggers the view update. It must be used to add a new property to a responsive object because Vue cannot detect ordinary new properties (such as this.myObject.newProperty = 'hi')

Note that the object cannot be a Vue instance or the root data object of a Vue instance.

Element UI form element

Official website link

Dynamic form rendering

Here, axios is used to request local JSON data, static / JSON / form json

{
  "data":[
    {
      "showName": "full name",
      "showValue": null,
      "htmlElements": "Input box",
      "fieldLength": 10,
      "requiredOrNot": 1,
      "desc":"Please enter your name"
    },
    {
      "showName": "describe",
      "showValue": null,
      "htmlElements": "Text field",
      "fieldLength": 99,
      "requiredOrNot": 1,
      "desc":"Please enter a description"
    },
    {
      "showName": "hobby",
      "showValue": null,
      "htmlElements": "check box",
      "requiredOrNot": 1,
      "desc":"Please choose a hobby"
    },
    {
      "showName": "Gender",
      "showValue": null,
      "htmlElements": "Radio ",
      "requiredOrNot": 1
    },
    {
      "showName": "date of birth",
      "showValue": null,
      "htmlElements": "calendar control ",
      "requiredOrNot": 1,
      "desc":"Please select the date of birth"
    },
    {
      "showName": "Time of marriage",
      "showValue": null,
      "htmlElements": "calendar control ",
      "requiredOrNot": 1,
      "desc":"Please choose a wedding time"
    },
    {
      "showName": "occupation",
      "showValue": null,
      "htmlElements": "Drop down box",
      "requiredOrNot": 1,
      "desc":"Please select occupation"
    }
  ]
}

Test.vue file

<template>
    <div>
        <h2>Test dynamic form</h2>
      <el-form :model="fieldObj" ref="ruleForm" label-width="180px" class="demo-ruleForm">
        <template v-for="(item,index) of fieldArray">
          <template v-if="item.htmlElements==='Input box'">
            <el-form-item :label="item.showName">
              <el-input v-model="fieldObj[item.showName]" :max="item.fieldLength" :placeholder="item.desc" show-word-limit></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='Text field'">
            <el-form-item :label="item.showName">
              <el-input type="textarea" rows="4" :placeholder="item.desc" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='calendar control '">
            <el-form-item :prop="item.showName" :label="item.showName">
              <el-date-picker v-model="fieldObj[item.showName]" :name="item.showName" type="date"
                              format="yyyy-MM-dd" value-format="yyyy-MM-dd"
                              :placeholder="item.desc"
              ></el-date-picker>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='Drop down box'">
            <el-form-item  :label="item.showName">
              <el-select v-model="fieldObj[item.showName]" :placeholder="item.describe">
                <el-option
                  v-for="items in job"
                  :key="items.name"
                  :label="items.name"
                  :value="items.value">
                </el-option>
              </el-select>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='Radio '">
            <el-form-item  :label="item.showName">
              <template v-for="(child,index) in sex">
                <el-radio v-model="fieldObj[item.showName]" :label="child.value">{{child.name}}</el-radio>
              </template>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='check box'">
            <el-form-item  :label="item.showName">
              <el-checkbox-group v-model="fieldObj[item.showName]">
                <template v-for="(child,index) of hobbies">
                  <el-checkbox :label="child.name"></el-checkbox>
                </template>
              </el-checkbox-group>
            </el-form-item>
          </template>
        </template>
      </el-form>
    </div>
</template>

<script>
  import axios from 'axios'
    export default {
        name: "Test",
      data(){
          return{
            fieldArray:[],// Form field collection
            fieldObj:{},
            sex:[{    // Gender
                name:'male',
                value:"male"
              },{
                name:"female",
                value:"female"
            }
            ],
            hobbies:[ // hobby
              {
                name:"having dinner",
                value:"having dinner"
              },{
                name:"play a game",
                value:"play a game"
              },{
                name:"Beat beans",
                value:"Beat beans"
              },
            ],
            job:[{  // occupation
                name:"doctor",
                value:"doctor"
              },{
                name:"teacher",
                value:"teacher"
              },{
                name:"driver",
                value:"driver"
            }
            ]
          }
      },
      mounted(){
        this.getFieldData();
      },
      methods:{
          getFieldData(){ // Get dynamic form data
            axios.get("../static/json/form.json").then(data=>{
              let response=data.data.data;
              this.fieldArray=response;
              for(let i=0;i<response.length;i++){
                let item=response[i];
                if(item.htmlElements==='check box'){
                  this.$set(this.fieldObj,item.showName,[]);
                }else {
                  this.$set(this.fieldObj,item.showName,item.showValue);
                }
              }
            })
          }
      }
    }
</script>

<style scoped>

</style>

Now, the forms have been rendered and bidirectional binding has been realized. What needs to be done now is how to realize dynamic form verification.

Explanation on the official website: the Form component provides the function of Form verification. You only need to pass in the agreed verification rules through the rules attribute and set the prop attribute of Form item to the field name to be verified,

  • prop field
  • rules
  • model

Here, the rules are set to be dynamic rather than written in advance in data. Here, we need to know the trigger form of each type

  • Input box / text field trigger: 'blur'
  • Radio box / check box / calendar control / drop-down box trigger: 'change'

Dynamic form validation

After knowing every form of verification in the form, test The files in Vue become

<template>
    <div>
        <h2>Test dynamic form</h2>
      <el-form :model="fieldObj" ref="ruleForm" label-width="180px" class="demo-ruleForm">
        <template v-for="(item,index) of fieldArray">
          <template v-if="item.htmlElements==='Input box'">
            <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: 'Please enter'+item.showName, trigger: 'blur' }]:[]">
              <el-input v-model="fieldObj[item.showName]" :max="item.fieldLength"
                        :placeholder="item.desc" show-word-limit ></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='Text field'">
            <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: 'Please enter'+item.showName, trigger: 'blur' }]:[]">
              <el-input type="textarea" rows="4" :placeholder="item.desc" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit></el-input>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='calendar control '">
            <el-form-item :prop="item.showName" :label="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: 'Please select'+item.showName, trigger: 'change' }]:[]">
              <el-date-picker v-model="fieldObj[item.showName]" :name="item.showName" type="date"
                              format="yyyy-MM-dd" value-format="yyyy-MM-dd"
                              :placeholder="item.desc"
              ></el-date-picker>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='Drop down box'">
            <el-form-item  :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: 'Please select'+item.showName, trigger: 'change' }]:[]">
              <el-select v-model="fieldObj[item.showName]" :placeholder="item.describe">
                <el-option
                  v-for="items in job"
                  :key="items.name"
                  :label="items.name"
                  :value="items.value">
                </el-option>
              </el-select>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='Radio '">
            <el-form-item  :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: 'Please select'+item.showName, trigger: 'change' }]:[]">
              <template v-for="(child,index) in sex">
                <el-radio v-model="fieldObj[item.showName]" :label="child.value">{{child.name}}</el-radio>
              </template>
            </el-form-item>
          </template>
          <template v-if="item.htmlElements==='check box'">
            <el-form-item  :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: 'Please select'+item.showName, trigger: 'change' }]:[]">
              <el-checkbox-group v-model="fieldObj[item.showName]">
                <template v-for="(child,index) of hobbies">
                  <el-checkbox :label="child.name"></el-checkbox>
                </template>
              </el-checkbox-group>
            </el-form-item>
          </template>
        </template>
        <div class="text-align">
          <el-button type="primary" @click="submitForm('ruleForm')">Create now</el-button>
          <el-button @click="resetForm('ruleForm')">Reset</el-button>
        </div>
      </el-form>
    </div>
</template>

<script>
  import axios from 'axios'
    export default {
        name: "Test",
      data(){
          return{
            fieldArray:[],// Form field collection
            fieldObj:{},
            sex:[{    // Gender
                name:'male',
                value:"male"
              },{
                name:"female",
                value:"female"
            }
            ],
            hobbies:[ // hobby
              {
                name:"having dinner",
                value:"having dinner"
              },{
                name:"play a game",
                value:"play a game"
              },{
                name:"Beat beans",
                value:"Beat beans"
              },
            ],
            job:[{  // occupation
                name:"doctor",
                value:"doctor"
              },{
                name:"teacher",
                value:"teacher"
              },{
                name:"driver",
                value:"driver"
            }
            ]
          }
      },
      mounted(){
        this.getFieldData();
      },
      methods:{
          getFieldData(){ // Get dynamic form data
            axios.get("../static/json/form.json").then(data=>{
              let response=data.data.data;
              this.fieldArray=response;
              for(let i=0;i<response.length;i++){
                let item=response[i];
                if(item.htmlElements==='check box'){
                  this.$set(this.fieldObj,item.showName,[]);
                }else {
                  this.$set(this.fieldObj,item.showName,item.showValue);
                }
              }
            })
          },
        submitForm(formName){ // Submit validation
          this.$refs[formName].validate((valid) => {
            if (valid) {
              console.log('Submit data');
            } else {
              return false;
            }
          });
        },
        resetForm(formName) { // Reset Form 
          this.$refs[formName].resetFields();
        }
      }
    }
</script>

<style scoped>

</style>

New contents include:

  • El form item added: prop = "item.showName"
  • El form item added: rules = "item. Requiredornot = = 1? [{required: true, message: 'please select' + item.showName, trigger: 'change'}]: []"
  • El form item added: rules = "item. Requiredornot = = 1? [{required: true, message: 'please enter' + item.showName, trigger: 'blur'}]: []"
  • Verification methods and methods for resetting forms are added in methods

vant dynamic form validation

Since the pc terminal and the mobile terminal are used together, we also realize the function of dynamic form on the mobile terminal,

Don't talk too much nonsense!

Or take test Vue component as an example, for the mobile terminal, vant dependency needs to be installed first. By default, it has been installed.

vant official website

Dynamic form rendering

Since there is no drop-down box component on the mobile terminal, instead of using the picker selector, you need to think about how to realize one-to-one correspondence for multiple pickers? What should I do?

form.json adds an object - City, and the previous code can still be reused

{
    "showName": "city",
    "showValue": null,
    "htmlElements": "Drop down box",
    "requiredOrNot": 1,
    "desc":"Please select occupation"
}

In this way, there are multiple drop-down boxes to solve the problem of multiple picker s.

Test. Code of Vue

html code area

<template>
    <div>
      <h2 class="title">test vant Dynamic form</h2>
      <van-form @submit="submitClaim">
        <template v-for="(item,index) of fieldArray">
          <template v-if="item.htmlElements==='Input box'">
            <van-field :maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"/>
          </template>
          <template v-if="item.htmlElements==='Text field'">
            <van-field rows="2"  autosize :label="item.showName" :name="item.showName" type="textarea"  v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit/>
          </template>
          <template v-if="item.htmlElements==='calendar control '">
            <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" />
          </template>
          <template v-if="item.htmlElements==='check box'">
            <van-field :name="item.showName" :label="item.showName">
              <template #input>
                <van-checkbox-group v-model="fieldObj[item.showName]" direction="horizontal">
                  <template v-for="(child,index) of hobbies">
                    <van-checkbox :name="child.value">{{child.name}}</van-checkbox>
                  </template>
                </van-checkbox-group>
              </template>
            </van-field>
          </template>
          <template v-if="item.htmlElements==='Radio '">
            <van-field :name="item.showName" :label="item.showName">
              <template #input>
                <van-radio-group v-model="fieldObj[item.showName]" direction="horizontal">
                  <template v-for="(child,index) of sex">
                    <van-radio :name="child.value">{{child.name}}</van-radio>
                  </template>
                </van-radio-group>
              </template>
            </van-field>
          </template>
          <template v-if="item.htmlElements==='Drop down box'">
            <van-field :name="item.showName" is-link :label="item.showName"  :readonly="true" v-model="fieldObj[item.showName]"/>
          </template>
        </template>
      </van-form>
    </div>
</template>

JavaScript code area

  import axios from 'axios'
    export default {
        name: "Test",
      data(){
          return{
            fieldArray:[],// Form field collection
            fieldObj:{},
            sex:[{    // Gender
              name:'male',
              value:"male"
            },{
              name:"female",
              value:"female"
            }
            ],
            hobbies:[ // hobby
              {
                name:"having dinner",
                value:"having dinner"
              },{
                name:"play a game",
                value:"play a game"
              },{
                name:"Beat beans",
                value:"Beat beans"
              },
            ],
          }
      },
      mounted(){
        this.getFieldArray();
      },
      methods:{
        getFieldArray(){  // Get json data of local dynamic form configuration
             axios.get("../../static/json/form.json").then(data=>{
               let response=data.data.data;
               this.fieldArray=response;
               for(let i=0;i<response.length;i++){
                 let item=response[i];
                 if(item.htmlElements==='check box'){
                   this.$set(this.fieldObj,item.showName,[]);
                 }else {
                   this.$set(this.fieldObj,item.showName,item.showValue);
                 }
               }
             })
          },
        submitClaim(taskInfo){

        }
      }
    }

Now, the values of input box, text field, radio box and check box are basically bound in both directions. The next step is to solve the one-to-one correspondence between the values of multiple calendar boxes and drop-down boxes.

The display and hiding of calendar box and pop-up layer are controlled by v-model, so you only need to know the number of calendar box and pop-up layer, and then cycle through the processing, and the getFieldArray method reprocesses it

axios.get("../../static/json/form.json").then(data=>{
    let response=data.data.data;
    this.fieldArray=response;
    for(let i=0;i<response.length;i++){
        let item=response[i];
        if(item.htmlElements==='check box'){
            this.$set(this.fieldObj,item.showName,[]);
        }else if(item.htmlElements==='calendar control '){
            this.$set(this.dateObj,item.showName,false); // Hide all calendar controls first
            this.$set(this.fieldObj,item.showName,item.showValue);
        }else if(item.htmlElements=='Drop down box'){
            this.$set(this.fieldObj,item.showName,item.showValue);
            this.$set(this.dropDownObj,item.showName,false); // Hide all pop-up layers first
        }else {
            this.$set(this.fieldObj,item.showName,item.showValue);
        }
    }
})

Add dateObj object in data

dateObj:{},// Controls the display and hiding of dates
Process calendar control

Add relevant content to html page

 <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dateObj[item.showName]=true"/>
<template v-for="(item,key,index) of dateObj">
   <van-calendar v-model="dateObj[key]" @confirm="(date)=>onConfirmTime(date,item,key)"/>
 </template>

Methods new methods

onConfirmTime(date,item,key){ // calendar control 
    this.fieldObj[key]=this.formatDate(date);
    this.dateObj[key]=false;
},
formatDate(date) {  // format date
    let year=date.getFullYear();
    let month=date.getMonth()+1;
    let day=date.getDate();
    if(month<10){
        month='0'+month;
    }
    if(day<10){
        day='0'+day;
    }
    return `${year}-${month}-${day}`;
},

Use v-model to bind the date object dateObj written in advance, and then traverse the object to control the display and hiding of each calendar control.

Bind the corresponding key value so that you can get the corresponding value of each calendar object after clicking.

Process drop-down box

Add dropDownObj object, dropDownTempObj object and dropdownmap object in data

dropDownObj:{},// Controls the display and hiding of the drop-down box
dropDownTempObj:{},// Drop down box object, which is used for the value in picker
dropDownMap:new Map(),

Added in the mounted life cycle

this.dropDownMap.set("occupation",["doctor","teacher","driver"]);
this.dropDownMap.set("city",["Beijing","Shanghai","Guangzhou","Shenzhen"])

Add html content to the page

<van-field :name="item.showName" is-link :label="item.showName"  :readonly="true" v-model="fieldObj[item.showName]" @click="dropDownObj[item.showName]=true"/>
<template v-for="(item,key,index) of dropDownObj">
    <van-popup v-model="dropDownObj[key]" position="bottom" :style="{width: '100%'}">
        <van-picker show-toolbar  @confirm="(value)=>onConfirmDropdown(value,key)" @cancel="dropDownObj[key]=false" :columns="handleData(dropDownTempObj[key])"/>
    </van-popup>
</template>

Methods add related methods

onConfirmDropdown(value,key){  // Select data from the drop-down box
  this.dropDownObj[key]=false;
  this.fieldObj[key]=value;
},
handleData(key){ // Drop down box to get each configuration item
  return this.dropDownMap.get(key);
},

getFieldArray method override

axios.get("../../static/json/form.json").then(data=>{
    let response=data.data.data;
    this.fieldArray=response;
    for(let i=0;i<response.length;i++){
        let item=response[i];
        if(item.htmlElements==='check box'){
            this.$set(this.fieldObj,item.showName,[]);
        }else if(item.htmlElements==='calendar control '){
            this.$set(this.dateObj,item.showName,false); // Hide all calendar controls first
            this.$set(this.fieldObj,item.showName,item.showValue);
        }else if(item.htmlElements=='Drop down box'){
            this.$set(this.fieldObj,item.showName,item.showValue);
            this.$set(this.dropDownObj,item.showName,false); // Hide all pop-up layers first
            this.$set(this.dropDownTempObj,item.showName,item.showName);
        }else {
            this.$set(this.fieldObj,item.showName,item.showValue);
        }
    }
})

Final effect

It can be seen that all the data has achieved two-way binding. The data submitted to the background is the data in the form, which can also be obtained. Finally, what needs to be realized is the verification function of the form.

Dynamic form validation

The verification of input boxes and text fields is relatively simple. You only need to add required and rules verification rules

Input boxes and text fields

<van-field
 :required="item.requiredOrNot==1?true:false":maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"  :rules="[{ required: true, message: 'Please fill in'+item.showName }]"/>

In this way, the verification of input box and text field is basically realized. As for the verification of other form types, the author is still studying

vant dynamic form handles all the code

html code snippet

<van-form @submit="submitClaim">
    <template v-for="(item,index) of fieldArray">
        <template v-if="item.htmlElements==='Input box'">
            <van-field :maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"/>
        </template>
        <template v-if="item.htmlElements==='Text field'">
            <van-field rows="2"  autosize :label="item.showName" :name="item.showName" type="textarea"  v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit/>
        </template>
        <template v-if="item.htmlElements==='calendar control '">
            <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dateObj[item.showName]=true"/>
        </template>
        <template v-if="item.htmlElements==='check box'">
            <van-field :name="item.showName" :label="item.showName">
                <template #input>
                    <van-checkbox-group v-model="fieldObj[item.showName]" direction="horizontal">
                        <template v-for="(child,index) of hobbies">
                            <van-checkbox :name="child.value">{{child.name}}</van-checkbox>
                        </template>
                    </van-checkbox-group>
                </template>
            </van-field>
        </template>
        <template v-if="item.htmlElements==='Radio '">
            <van-field :name="item.showName" :label="item.showName">
                <template #input>
                    <van-radio-group v-model="fieldObj[item.showName]" direction="horizontal">
                        <template v-for="(child,index) of sex">
                            <van-radio :name="child.value">{{child.name}}</van-radio>
                        </template>
                    </van-radio-group>
                </template>
            </van-field>
        </template>
        <template v-if="item.htmlElements==='Drop down box'">
            <van-field :name="item.showName" is-link :label="item.showName"  :readonly="true" v-model="fieldObj[item.showName]" @click="dropDownObj[item.showName]=true"/>
        </template>
    </template>
    <van-button  type="info" round  native-type="submit" :style="{width:'100%',marginTop:'15px'}">Submit</van-button>
</van-form>
<template v-for="(item,key,index) of dateObj">
    <van-calendar v-model="dateObj[key]" @confirm="(date)=>onConfirmTime(date,item,key)"/>
</template>
<template v-for="(item,key,index) of dropDownObj">
    <van-popup v-model="dropDownObj[key]" position="bottom" :style="{width: '100%'}">
        <van-picker show-toolbar  @confirm="(value)=>onConfirmDropdown(value,key)" @cancel="dropDownObj[key]=false" :columns="handleData(dropDownTempObj[key])"/>
    </van-popup>
</template>

JavaScript code snippet

import axios from 'axios'
export default {
    name: "Test",
    data(){
        return{
            fieldArray:[],// Form field collection
            fieldObj:{},
            sex:[{    // Gender
                name:'male',
                value:"male"
            },{
                name:"female",
                value:"female"
            }
                ],
            hobbies:[ // hobby
                {
                    name:"having dinner",
                    value:"having dinner"
                },{
                    name:"play a game",
                    value:"play a game"
                },{
                    name:"Beat beans",
                    value:"Beat beans"
                },
            ],
            dateObj:{ // Controls the display and hiding of dates

            },
            dropDownObj:{ // Controls the display and hiding of the drop-down box

            },
            dropDownTempObj:{ // Drop down box object, which is used for the value in picker

            },
            dropDownMap:new Map(),
        }
    },
    mounted(){
        this.getFieldArray();
        this.dropDownMap.set("occupation",["doctor","teacher","driver"]);
        this.dropDownMap.set("city",["Beijing","Shanghai","Guangzhou","Shenzhen"])
    },
    methods:{
        getFieldArray(){  // Get json data of local dynamic form configuration
            axios.get("../../static/json/form.json").then(data=>{
                let response=data.data.data;
                this.fieldArray=response;
                for(let i=0;i<response.length;i++){
                    let item=response[i];
                    if(item.htmlElements==='check box'){
                        this.$set(this.fieldObj,item.showName,[]);
                    }else if(item.htmlElements==='calendar control '){
                        this.$set(this.dateObj,item.showName,false); // Hide all calendar controls first
                        this.$set(this.fieldObj,item.showName,item.showValue);
                    }else if(item.htmlElements=='Drop down box'){
                        this.$set(this.fieldObj,item.showName,item.showValue);
                        this.$set(this.dropDownObj,item.showName,false); // Hide all pop-up layers first
                        this.$set(this.dropDownTempObj,item.showName,item.showName);
                    }else {
                        this.$set(this.fieldObj,item.showName,item.showValue);
                    }
                }
            })
        },
        onConfirmTime(date,item,key){ // calendar control 
            this.fieldObj[key]=this.formatDate(date);
            this.dateObj[key]=false;
        },
        onConfirmDropdown(value,key){  // Select data from the drop-down box
            this.dropDownObj[key]=false;
            this.fieldObj[key]=value;
        },
        handleData(key){ // Drop down box to get each configuration item
            return this.dropDownMap.get(key);
        },
        formatDate(date) {  // format date
            let year=date.getFullYear();
            let month=date.getMonth()+1;
            let day=date.getDate();
            if(month<10){
                month='0'+month;
            }
            if(day<10){
                day='0'+day;
            }
            return `${year}-${month}-${day}`;
        },
        submitClaim(taskInfo){
            console.log(taskInfo);
        }
    }
}

summary

On the whole, the processing of dynamic forms is not very difficult. What needs to be done is how to process the data. Of course, there are still deficiencies in the processing of file upload, the optimization degree of the code is not done well, and there are a lot of v-if written in v-for. Whether a single component can be used for processing needs to be considered.

ending

If you think this blog is helpful to you, remember to praise the author for three times 👍👍👍, Attention, collection and your support are the biggest driving force in my writing. See you in the next article.

Keywords: Front-end Vue Vue.js

Added by rline101 on Tue, 01 Feb 2022 22:59:25 +0200