项目需求,需要根据后台接口返回数据,动态添加表单内容
说明:此组件基于Ant Design of Vue
目前支持六种表单控件:文本输入框(TextInput)、文本域输入框(TextArea)、下拉选择框(SelectInput)、下拉多选(SelectMultiple)、日期(DataPicker)、日期精确到秒(DataPickerSen)
一、文本框
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>
二、文本域
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>
三、下拉框
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>
四、日期
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>
五、表单生成逻辑
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 || ‘提交‘, 50 onResetText: this.config.buttons.onResetText || ‘重置‘ 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>
六、调用
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: ‘确定‘, 21 onResetText: ‘取消‘ 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>
后台接口数据格式和页面样式可以参考,请根据自己的业务需求做相应调整,以下为我的项目后台接口数据格式
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": "河道(段)名称", 14 "fieldType": "TextInput", 15 "placeHolder": null 16 }, { 17 "fieldName": "sp_code", 18 "name": "sp_code", 19 "options": [], 20 "label": "水普编号", 21 "fieldType": "TextInput", 22 "placeHolder": null 23 }], "fieldClassify": ‘基本信息‘ 24 }, { 25 "fields": [{ 26 "fieldName": "brief_name", 27 "name": "brief_name", 28 "options": [], 29 "label": "河道(段)简称", 30 "fieldType": "TextInput", 31 "placeHolder": null 32 }, { 33 "fieldName": "simplegeometry", 34 "name": "simplegeometry", 35 "options": [], 36 "label": "抽稀几何", 37 "fieldType": "TextInput", 38 "placeHolder": null 39 }], "fieldClassify": ‘附件信息‘ 40 }, ], 41 buttons: { 42 onSubmitText: ‘确定‘, 43 onResetText: ‘取消‘ 44 } 45 }
原文地址:https://www.cnblogs.com/wzq201607/p/vue_genForm.html
时间: 2024-11-05 14:51:37