vue dynamic form

Keywords: PHP axios less Vue

According to the requirement of the project, the data should be returned according to the background interface, and the form content should be added dynamically.

 

Description: This component is based on Ant Design of Vue

 

Six form controls are currently supported: Text Input, Text Area, Select Input, Select Multiple, Data Picker, and Data Picker Sen.

 

Text Box

 

 1 <template>
 2   <a-form-item :label="label" v-bind="formItemLayout">
 3     <a-input
 4       v-decorator="[`${fieldName}`, {initialValue: currentValue}]"
 5       :placeholder="placeHolder"
 6       @input="onInputEvent"
 7     />
 8   </a-form-item>
 9 </template>
10 
11 <script>
12 export default {
13   name: 'TextInput',
14   props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
15   data() {
16     return {
17       currentValue: this.value,
18       formItemLayout: {
19         labelCol: {
20           xs: { span: 24 },
21           sm: { span: 8 }
22         },
23         wrapperCol: {
24           xs: { span: 24 },
25           sm: { span: 12 }
26         }
27       }
28     }
29   },
30   methods: {
31     onInputEvent(v) {
32       this.$emit('input', this.name, v.target.value)
33     }
34   },
35   watch: {
36     value(val) {
37       this.currentValue = val
38     }
39   }
40 }
41 </script>

 

II. Text Domain

 1 <template>
 2   <a-form-item :label="label" v-bind="formItemLayout">
 3     <a-textarea
 4       v-decorator="[`${fieldName}`, {initialValue: currentValue}]"
 5       :placeholder="placeHolder"
 6       @input="onInputEvent"
 7     />
 8   </a-form-item>
 9 </template>
10 
11 <script>
12 export default {
13   name: 'TextArea',
14   props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
15   data() {
16     return {
17       currentValue: this.currentValue,
18       formItemLayout: {
19         labelCol: {
20           xs: { span: 24 },
21           sm: { span: 8 }
22         },
23         wrapperCol: {
24           xs: { span: 24 },
25           sm: { span: 12 }
26         }
27       }
28     }
29   },
30   methods: {
31     onInputEvent(v) {
32       this.$emit('input', this.name, v.target.value)
33     }
34   },
35   watch: {
36     currentValue(val) {
37       this.currentValue = val
38     }
39   }
40 }
41 </script>

3. Drop-down box

 1 <template>
 2   <a-form-item :label="label" v-bind="formItemLayout">
 3     <a-select
 4       v-decorator="[`${fieldName}`, {initialValue: currentValue}]"
 5       :placeholder="placeHolder"
 6       @change="onInputEvent"
 7     >
 8       <a-select-option v-for="v in options" :key="v.dictId">{{v.dictName}}</a-select-option>
 9     </a-select>
10   </a-form-item>
11 </template>
12 
13 <script>
14 export default {
15   name: 'SelectInput',
16   props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
17   data() {
18     return {
19       currentValue: this.value,
20       formItemLayout: {
21         labelCol: {
22           xs: { span: 24 },
23           sm: { span: 8 }
24         },
25         wrapperCol: {
26           xs: { span: 24 },
27           sm: { span: 12 }
28         }
29       }
30     }
31   },
32   methods: {
33     onInputEvent(value) {
34       this.$emit('input', this.name, value)
35     }
36   },
37   watch: {
38     value(val) {
39       this.currentValue = val
40     }
41   }
42 }
43 </script>

Four, date

 1 <template>
 2   <a-form-item :label="label" v-bind="formItemLayout">
 3     <a-date-picker
 4       :defaultValue="moment(currentValue, 'YYYY-MM-DD')"
 5       :placeholder="placeHolder"
 6       @change="onInputEvent"
 7     />
 8   </a-form-item>
 9 </template>
10 
11 <script>
12 import moment from 'moment'
13 
14 export default {
15   name: 'DataPicker',
16   props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
17   data() {
18     return {
19       currentValue: this.value,
20       formItemLayout: {
21         labelCol: {
22           xs: { span: 24 },
23           sm: { span: 8 }
24         },
25         wrapperCol: {
26           xs: { span: 24 },
27           sm: { span: 12 }
28         }
29       }
30     }
31   },
32   methods: {
33     moment,
34     onInputEvent(value) {
35       this.$emit('input', this.name, value.format('YYYY-MM-DD'))
36     }
37   },
38   watch: {
39     value(val) {
40       this.currentValue = val
41     }
42   }
43 }
44 </script>

Form Generation Logic

 1 <template>
 2   <div class="my-class">
 3     <a-form class="ant-advanced-search-form" :form="form">
 4       <a-row :gutter="24">
 5         <div v-for="(fieldConfig, index) in config.fieldsConfig" :key="index">
 6           <a-col :span="24">
 7             <a-divider>{{fieldConfig.fieldClassify}}</a-divider>
 8           </a-col>
 9           <a-col :span="12" v-for="(field, index) in fieldConfig.fields" :key="index">
10             <component
11               :key="index"
12               :is="field.fieldType"
13               :label="field.label"
14               :fieldName="field.fieldName"
15               :placeHolder="field.placeHolder"
16               :value="value[field.name]"
17               @input="updateForm"
18               v-bind="field"
19               :options="field.options"
20               :ref="field.name"
21             ></component>
22           </a-col>
23         </div>
24       </a-row>
25       <a-row>
26         <a-col :span="24" :style="{ textAlign: 'center', marginTop: '20px' }">
27           <a-button :style="{ marginRight: '8px' }" @click="reset">{{onResetText}}</a-button>
28           <a-button type="primary" @click="submit">{{onSubmitText}}</a-button>
29         </a-col>
30       </a-row>
31     </a-form>
32   </div>
33 </template>
34 <script>
35 import TextInput from './TextInput'
36 import TextArea from './TextArea'
37 import SelectInput from './SelectInput'
38 import SelectMultiple from './SelectMultiple'
39 import DataPicker from './PickerData'
40 import DataPickerSen from './PickerDataSen'
41 
42 export default {
43   name: 'FormGenerator',
44   components: { TextArea, TextInput, SelectInput, SelectMultiple, DataPicker, DataPickerSen },
45   props: ['config', 'value'],
46   data() {
47     return {
48       form: this.$form.createForm(this),
49       onSubmitText: this.config.buttons.onSubmitText || 'Submission',
50       onResetText: this.config.buttons.onResetText || 'Reset'
51     }
52   },
53   methods: {
54     updateForm(fieldName, v) {
55       this.value[fieldName] = v
56     },
57     submit() {
58       this.form.validateFields((error, values) => {
59         if (!error) {
60           this.$emit('submit')
61         }
62       })
63     },
64     reset() {
65       this.form.resetFields()
66     }
67   }
68 }
69 </script>
70 
71 <style lang="less" scoped>
72 .my-class {
73   height: 600px;
74   overflow-y: scroll;
75   overflow-x: hidden;
76 }
77 
78 .ant-advanced-search-form .ant-form-item {
79   display: flex;
80 }
81 
82 .ant-advanced-search-form .ant-form-item-control-wrapper {
83   flex: 1;
84 }
85 
86 #components-form-demo-advanced-search .ant-form {
87   max-width: none;
88 }
89 </style>

Six. Call

 1 <template>
 2   <div>
 3     <form-generator :config="config" @submit="getFormData" :value="formData"></form-generator>
 4   </div>
 5 </template>
 6 <script>
 7 import { axios } from '@/utils/request'
 8 import FormGenerator from './form/FormGenerator'
 9 
10 export default {
11   name: '',
12   props: {},
13   components: { FormGenerator },
14   data() {
15     return {
16       formData: {},
17       config: {
18         fieldsConfig: [],
19         buttons: {
20           onSubmitText: 'Determine',
21           onResetText: 'cancel'
22         }
23       }
24     }
25   },
26   methods: {
27     getFormData() {
28       console.log('formData', this.formData)
29     },
30     queryAllFields() {
31       axios.get(``).then(result => {
32         if (result && result.code === 0) {
33           this.config.fieldsConfig = result.fieldConfig
34         } else {
35           this.$message.error(result.msg)
36         }
37       })
38     }
39   }
40 }
41 </script>
42 <style lang="less" scoped>
43 </style>

Background interface data format and page style can be referred to. Please adjust it accordingly according to your own business needs. The following is the background interface data format for my project.

 1 formData: {
 2     "river_name": '',
 3     "sp_code": '',
 4     "brief_name": '',
 5     "simplegeometry": ''
 6 },
 7 config: {
 8     fieldsConfig: [{
 9         "fields":  [{
10             "fieldName": "river_name",
11             "name": "river_name",
12             "options": [],
13             "label": "Name of river course (section)",
14             "fieldType": "TextInput",
15             "placeHolder": null
16         }, {
17             "fieldName": "sp_code",
18             "name": "sp_code",
19             "options": [],
20             "label": "Water code",
21             "fieldType": "TextInput",
22             "placeHolder": null
23         }], "fieldClassify": 'Essential information'
24     }, {
25         "fields":  [{
26             "fieldName": "brief_name",
27             "name": "brief_name",
28             "options": [],
29             "label": "Abbreviation of river course (section)",
30             "fieldType": "TextInput",
31             "placeHolder": null
32         }, {
33             "fieldName": "simplegeometry",
34             "name": "simplegeometry",
35             "options": [],
36             "label": "Sparse geometry",
37             "fieldType": "TextInput",
38             "placeHolder": null
39         }], "fieldClassify": 'Attachment information'
40     }, ],
41     buttons: {
42         onSubmitText: 'Determine',
43         onResetText: 'cancel'
44     }
45 }

Posted by aalmos on Sun, 13 Oct 2019 10:09:55 -0700