vue动态表单
项目需求,需要根据后台接口返回数据,动态添加表单内容
说明:此组件基于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动态表单的更多相关文章
- Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)
Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...
- vue 开发系列(八) 动态表单开发
概要 动态表单指的是我们的表单不是通过vue 组件一个个编写的,我们的表单是根据后端生成的vue模板,在前端通过vue构建出来的.主要的思路是,在后端生成vue的模板,前端通过ajax的方式加载后端的 ...
- vue+element 动态表单验证
公司最近的项目有个添加动态表单的需求,总结一下我在表单验证上遇到的一些坑. 如图是功能的需求,这个功能挺好实现的,但是表单验证真是耗费了我一些功夫. vue+element在表单验证上有一些限制,必须 ...
- 循序渐进VUE+Element 前端应用开发(27)--- 数据表的动态表单设计和数据存储
在我们一些系统里面,有时候会需要一些让用户自定义的数据信息,一般这些可以使用扩展JSON进行存储,不过每个业务表的显示项目可能不一样,因此需要根据不同的表单进行设计,然后进行对应的数据存储.本篇随笔结 ...
- ElementUI表单验证攻略:解决表单项启用和禁用验证的切换,以及动态表单验证的综合性问题
试想一种比较复杂的业务场景: 表格(el-table)的每一行数据的第一列是勾选框,最后一列是输入框.当某一行的勾选框勾上时,启用该行的输入框,并开启该行输入框的表单验证:取消该行的勾选框,则禁用该行 ...
- antd+vue3实现动态表单的自动校验
由于vue3用的人还不多,所以有些问题博主踩了坑只能自己爬出来了,特此做个记录.如有错误,请大家指正. 回归正题,我所做的业务是,动态添加表单项,对每一项单独做校验,效果如下: 主要代码如下: 1 & ...
- [K/3Cloud] 如何从被调用的动态表单界面返回数据
在需要返回数据的地方调用表单返回方法完成数据返回 this.View.ReturnToParentWindow(retData); 在调用界面的回调函数中取出返回结果的ReturnData即可使用. ...
- vue的表单编辑删除,保存取消功能
过年回来第一篇博客,可能说的不是很清楚,而且心情可能也不是特别的high,虽然今天是元宵,我还在办公室11.30在加班,但就是想把写过的代码记下来,怕以后可能真的忘了.(心将塞未塞,欲塞未满) VUE ...
- 简易OA漫谈之工作流设计(六,快捷表单和动态表单)
如果没有表单设计功能,我们一般建物理表,再把表单挂接到流程, 我们可以把外接表单的地址填到表单地址中,地址中会传递一个id. 如果使用外接表单,在审批的时候可能会“不太友好”,因为在审批单上看不到任何 ...
随机推荐
- Django中信号signals简单使用
在平时的开发过程中,我们会遇到一些特殊的应用场景,如果你想要在执行某种操作之前或者之后你能够得到通知,并对其进行一些你想要的操作时,你就可以用Django中的信号(signals).Django 提供 ...
- vscode左边侧边栏字体的大小
相信很多小伙伴们都会在用vscode的时候,当屏幕大小发生变化的时候,你可能会觉得左边的字体太小了,我也遇到了这样的问题,百度也没有找到解决办法,自己摸索了几天,发现可以通过ctrl+shift+ + ...
- PATA 1065 A+B and C (64bit)
1065. A+B and C (64bit) (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 HOU, Qiming G ...
- Mac安装MySQL-python报错解决
Mac安装MySQL-pyhton报错 今天在Mac上安装MySQL-python报错,搜遍网络都说什么mysql config路径问题,但是都不行. 解决方案 一开始遇到的问题是: Complete ...
- 苹果二代TWS无线耳机AirPods调研
产品介绍 苹果AirPods二代自从2018年9月份上市以来,到现在将近一年的时间了,据江湖传闻,苹果AirPods的总售卖个数,已经超过了5000W部,这样价格的TWS耳机,能够卖那么多的量,估计也 ...
- c#基础四
写入一个XML文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; usin ...
- sql-实现select取行号、分组后在分组内排序、每个分组中的前n条数据
表结构设计: 实现select取行号 sql局部变量的2种方式 set @name='cm3333f'; select @id:=1; 区别:set 可以用=号赋值,而select 不行,必须使用:= ...
- 分布式个人理解概述和dubbo实现简述
什么是分布式?为什么使用分布式? 个人有一些浅薄的理解希望可以批评指正,从概念和应用 两个方面概述: 一.概念:分布式也叫分布式服务,也就是说 他是 一种面向服务思想的程序设计和架构风格,典 ...
- c++学习书籍推荐《The C++ Programming Language第四版》下载
百度云及其他网盘下载地址:点我 作者简介 Bjarne Stroustrup is the designer and original implementer of C++, the author o ...
- python数据库-MongoDB的安装(53)
一.NoSQL介绍 1.什么是NoSQL NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL". NoSQL,指的是非关系型的数据库.NoSQL有时也称 ...