项目需求,需要根据后台接口返回数据,动态添加表单内容

说明:此组件基于Ant Design of Vue

目前支持六种表单控件:文本输入框(TextInput)、文本域输入框(TextArea)、下拉选择框(SelectInput)、下拉多选(SelectMultiple)、日期(DataPicker)、日期精确到秒(DataPickerSen)

一、文本框

 <template>
<a-form-item :label="label" v-bind="formItemLayout">
<a-input
v-decorator="[`${fieldName}`, {initialValue: currentValue}]"
:placeholder="placeHolder"
@input="onInputEvent"
/>
</a-form-item>
</template> <script>
export default {
name: 'TextInput',
props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
data() {
return {
currentValue: this.value,
formItemLayout: {
labelCol: {
xs: { span: 24 },
sm: { span: 8 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 }
}
}
}
},
methods: {
onInputEvent(v) {
this.$emit('input', this.name, v.target.value)
}
},
watch: {
value(val) {
this.currentValue = val
}
}
}
</script>

二、文本域

 <template>
<a-form-item :label="label" v-bind="formItemLayout">
<a-textarea
v-decorator="[`${fieldName}`, {initialValue: currentValue}]"
:placeholder="placeHolder"
@input="onInputEvent"
/>
</a-form-item>
</template> <script>
export default {
name: 'TextArea',
props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
data() {
return {
currentValue: this.currentValue,
formItemLayout: {
labelCol: {
xs: { span: 24 },
sm: { span: 8 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 }
}
}
}
},
methods: {
onInputEvent(v) {
this.$emit('input', this.name, v.target.value)
}
},
watch: {
currentValue(val) {
this.currentValue = val
}
}
}
</script>

三、下拉框

 <template>
<a-form-item :label="label" v-bind="formItemLayout">
<a-select
v-decorator="[`${fieldName}`, {initialValue: currentValue}]"
:placeholder="placeHolder"
@change="onInputEvent"
>
<a-select-option v-for="v in options" :key="v.dictId">{{v.dictName}}</a-select-option>
</a-select>
</a-form-item>
</template> <script>
export default {
name: 'SelectInput',
props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
data() {
return {
currentValue: this.value,
formItemLayout: {
labelCol: {
xs: { span: 24 },
sm: { span: 8 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 }
}
}
}
},
methods: {
onInputEvent(value) {
this.$emit('input', this.name, value)
}
},
watch: {
value(val) {
this.currentValue = val
}
}
}
</script>

四、日期

 <template>
<a-form-item :label="label" v-bind="formItemLayout">
<a-date-picker
:defaultValue="moment(currentValue, 'YYYY-MM-DD')"
:placeholder="placeHolder"
@change="onInputEvent"
/>
</a-form-item>
</template> <script>
import moment from 'moment' export default {
name: 'DataPicker',
props: ['name', 'label', 'value', 'options', 'fieldName', 'placeHolder'],
data() {
return {
currentValue: this.value,
formItemLayout: {
labelCol: {
xs: { span: 24 },
sm: { span: 8 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 }
}
}
}
},
methods: {
moment,
onInputEvent(value) {
this.$emit('input', this.name, value.format('YYYY-MM-DD'))
}
},
watch: {
value(val) {
this.currentValue = val
}
}
}
</script>

五、表单生成逻辑

 <template>
<div class="my-class">
<a-form class="ant-advanced-search-form" :form="form">
<a-row :gutter="24">
<div v-for="(fieldConfig, index) in config.fieldsConfig" :key="index">
<a-col :span="24">
<a-divider>{{fieldConfig.fieldClassify}}</a-divider>
</a-col>
<a-col :span="12" v-for="(field, index) in fieldConfig.fields" :key="index">
<component
:key="index"
:is="field.fieldType"
:label="field.label"
:fieldName="field.fieldName"
:placeHolder="field.placeHolder"
:value="value[field.name]"
@input="updateForm"
v-bind="field"
:options="field.options"
:ref="field.name"
></component>
</a-col>
</div>
</a-row>
<a-row>
<a-col :span="24" :style="{ textAlign: 'center', marginTop: '20px' }">
<a-button :style="{ marginRight: '8px' }" @click="reset">{{onResetText}}</a-button>
<a-button type="primary" @click="submit">{{onSubmitText}}</a-button>
</a-col>
</a-row>
</a-form>
</div>
</template>
<script>
import TextInput from './TextInput'
import TextArea from './TextArea'
import SelectInput from './SelectInput'
import SelectMultiple from './SelectMultiple'
import DataPicker from './PickerData'
import DataPickerSen from './PickerDataSen' export default {
name: 'FormGenerator',
components: { TextArea, TextInput, SelectInput, SelectMultiple, DataPicker, DataPickerSen },
props: ['config', 'value'],
data() {
return {
form: this.$form.createForm(this),
onSubmitText: this.config.buttons.onSubmitText || '提交',
onResetText: this.config.buttons.onResetText || '重置'
}
},
methods: {
updateForm(fieldName, v) {
this.value[fieldName] = v
},
submit() {
this.form.validateFields((error, values) => {
if (!error) {
this.$emit('submit')
}
})
},
reset() {
this.form.resetFields()
}
}
}
</script> <style lang="less" scoped>
.my-class {
height: 600px;
overflow-y: scroll;
overflow-x: hidden;
} .ant-advanced-search-form .ant-form-item {
display: flex;
} .ant-advanced-search-form .ant-form-item-control-wrapper {
flex: 1;
} #components-form-demo-advanced-search .ant-form {
max-width: none;
}
</style>

六、调用

 <template>
<div>
<form-generator :config="config" @submit="getFormData" :value="formData"></form-generator>
</div>
</template>
<script>
import { axios } from '@/utils/request'
import FormGenerator from './form/FormGenerator' export default {
name: '',
props: {},
components: { FormGenerator },
data() {
return {
formData: {},
config: {
fieldsConfig: [],
buttons: {
onSubmitText: '确定',
onResetText: '取消'
}
}
}
},
methods: {
getFormData() {
console.log('formData', this.formData)
},
queryAllFields() {
axios.get(``).then(result => {
if (result && result.code === 0) {
this.config.fieldsConfig = result.fieldConfig
} else {
this.$message.error(result.msg)
}
})
}
}
}
</script>
<style lang="less" scoped>
</style>

后台接口数据格式和页面样式可以参考,请根据自己的业务需求做相应调整,以下为我的项目后台接口数据格式

 formData: {
"river_name": '',
"sp_code": '',
"brief_name": '',
"simplegeometry": ''
},
config: {
fieldsConfig: [{
"fields": [{
"fieldName": "river_name",
"name": "river_name",
"options": [],
"label": "河道(段)名称",
"fieldType": "TextInput",
"placeHolder": null
}, {
"fieldName": "sp_code",
"name": "sp_code",
"options": [],
"label": "水普编号",
"fieldType": "TextInput",
"placeHolder": null
}], "fieldClassify": '基本信息'
}, {
"fields": [{
"fieldName": "brief_name",
"name": "brief_name",
"options": [],
"label": "河道(段)简称",
"fieldType": "TextInput",
"placeHolder": null
}, {
"fieldName": "simplegeometry",
"name": "simplegeometry",
"options": [],
"label": "抽稀几何",
"fieldType": "TextInput",
"placeHolder": null
}], "fieldClassify": '附件信息'
}, ],
buttons: {
onSubmitText: '确定',
onResetText: '取消'
}
}

vue动态表单的更多相关文章

  1. Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)

    Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...

  2. vue 开发系列(八) 动态表单开发

    概要 动态表单指的是我们的表单不是通过vue 组件一个个编写的,我们的表单是根据后端生成的vue模板,在前端通过vue构建出来的.主要的思路是,在后端生成vue的模板,前端通过ajax的方式加载后端的 ...

  3. vue+element 动态表单验证

    公司最近的项目有个添加动态表单的需求,总结一下我在表单验证上遇到的一些坑. 如图是功能的需求,这个功能挺好实现的,但是表单验证真是耗费了我一些功夫. vue+element在表单验证上有一些限制,必须 ...

  4. 循序渐进VUE+Element 前端应用开发(27)--- 数据表的动态表单设计和数据存储

    在我们一些系统里面,有时候会需要一些让用户自定义的数据信息,一般这些可以使用扩展JSON进行存储,不过每个业务表的显示项目可能不一样,因此需要根据不同的表单进行设计,然后进行对应的数据存储.本篇随笔结 ...

  5. ElementUI表单验证攻略:解决表单项启用和禁用验证的切换,以及动态表单验证的综合性问题

    试想一种比较复杂的业务场景: 表格(el-table)的每一行数据的第一列是勾选框,最后一列是输入框.当某一行的勾选框勾上时,启用该行的输入框,并开启该行输入框的表单验证:取消该行的勾选框,则禁用该行 ...

  6. antd+vue3实现动态表单的自动校验

    由于vue3用的人还不多,所以有些问题博主踩了坑只能自己爬出来了,特此做个记录.如有错误,请大家指正. 回归正题,我所做的业务是,动态添加表单项,对每一项单独做校验,效果如下: 主要代码如下: 1 & ...

  7. [K/3Cloud] 如何从被调用的动态表单界面返回数据

    在需要返回数据的地方调用表单返回方法完成数据返回 this.View.ReturnToParentWindow(retData); 在调用界面的回调函数中取出返回结果的ReturnData即可使用. ...

  8. vue的表单编辑删除,保存取消功能

    过年回来第一篇博客,可能说的不是很清楚,而且心情可能也不是特别的high,虽然今天是元宵,我还在办公室11.30在加班,但就是想把写过的代码记下来,怕以后可能真的忘了.(心将塞未塞,欲塞未满) VUE ...

  9. 简易OA漫谈之工作流设计(六,快捷表单和动态表单)

    如果没有表单设计功能,我们一般建物理表,再把表单挂接到流程, 我们可以把外接表单的地址填到表单地址中,地址中会传递一个id. 如果使用外接表单,在审批的时候可能会“不太友好”,因为在审批单上看不到任何 ...

随机推荐

  1. 使用vscode调试Nodejs

    之前想用vscode调试nodejs,总是不成功,也走很多弯路,现在记录下来. 首先新建一个文件夹,用vscode打开这个文件夹, 用vscode自带的终端执行npm init,输入名称,其他的可不输 ...

  2. phpstorm+xdebug手机app调试

    1.安装过程网上搜一下全都是,这里省略. 2.由于debug调试需要去判断cookie中XDEBUG_SESSION,然后去调试.由于app接口请求没法去传,而且就算去传递也很麻烦,还要让app去改动 ...

  3. CI框架使用(一)

    CI框架的使用是很简单,也 是mvc模式.其中有好多类直接调用.   在使用帮助函数的时候,都需要手动加载,或者是在配置文件中加一个自动加载 $this->load->helper('ur ...

  4. 微服务SpringCloud之服务调用与负载均衡

    上一篇我们学习了服务的注册与发现,本篇博客是在上一篇的基础上学习服务的调用.上一博客主要创建了Eureka的服务端和一个Client,该Client包含了一个Controller用来提供对外服务供外部 ...

  5. 并发编程-concurrent指南-ReadWriteLock

    ReadWriteLock也是一个接口,在它里面只定义了两个方法: public interface ReadWriteLock { /** * Returns the lock used for r ...

  6. Java 中的字符串(String)与C# 中字符串(string)的异同

    1. C# 中比较两个字符串字面量是否相等,可以使用 “==”比较运算符,是因为string 类型重写(override)了“==” 和 “!=” 运算符,在使用“==” 和 “!=” 进行字符串比较 ...

  7. 深入学习Spring框架(一)- 入门

    1.Spring是什么? Spring是一个JavaEE轻量级的一站式开发框架. JavaEE: 就是用于开发B/S的程序.(企业级) 轻量级:使用最少代码启动框架,然后根据你的需求选择,选择你喜欢的 ...

  8. GStreamer基础教程04 - 动态连接Pipeline

    摘要 在以前的文章中,我们了解到了2种播放文件的方式:一种是在知道了文件的类型及编码方式后,手动创建所需Element并构造Pipeline:另一种是直接使用playbin,由playbin内部动态创 ...

  9. Java 7 源码学习系列(一)——String

    String表示字符串,Java中所有字符串的字面值都是String类的实例,例如“ABC”.字符串是常量,在定义之后不能被改变,字符串缓冲区支持可变的字符串.因为 String 对象是不可变的,所以 ...

  10. Spring中@value以及属性注入的学习

    1.简单的Java配置 配置文件(jdbc.properties) jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://1 ...