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

说明:此组件基于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. 常用的HTTP状态代码(4xx、5xx)详解

    HTTP状态代码常用的如下: 400 无法解析此请求. 401.1 未经授权:访问由于凭据无效被拒绝. 401.2 未经授权: 访问由于服务器配置倾向使用替代身份验证方法而被拒绝. 401.3 未经授 ...

  2. 前端Vue基础学习

    Vue基础 对与vue的简洁明了的干货分享,适合小白学习观看,如果有笔误或者想了解更多的,请给笔者留言,后续会继续分享,从零开始的vue相关经验 1.创建vue实例 <div id=" ...

  3. Java学习笔记——MySQL创建表结构

    一.创建/删除数据库. create database t14; drop database t14; use t14; 二.创建若干表用于测试 这里预留了几个坑,下面要填坑的.. /*创建学生表*/ ...

  4. 面试中的作用域题和THIS 指向的问题

    作用域的面试题 1. fn() function fn () { console.log(12) } var as = function () { console.log(45) } 2. var a ...

  5. Burp Suite 基础知识(一)

    前言 大家好,我是小白,下面开始我的表演,以下内容如有雷同纯属巧合,靴靴.  (鞠躬 学到什么就写什么,可能有点乱哈. Burp Suite 是一款用于攻击 web 应用程序的集成平台,包含了许多工具 ...

  6. Oracle Awr报告_awr报告解读_基础简要信息

    导出 关于awr报告的导出,上一篇博客已经进行过讲述了.博客链接地址:https://www.cnblogs.com/liyasong/p/oracle_report1.html  这里就不再赘述. ...

  7. kafka入门(二)分区和group

    topic 在kafka中消息是按照topic进行分类的:每条发布到Kafka集群的消息都有一个类别,这个类别被称为topic parition 一个topic可以配置几个parition,每一个分区 ...

  8. 深入理解C#的装箱和拆箱

    个人理解(本质): 封箱是把值类型转换为引用类型 拆箱是把引用类型转换为值类型 封箱是把值类型转换为System.Object类型,或者转换为由值类型实现的接口类型: 例如: struct Mystr ...

  9. 零基础ASP.NET Core MVC插件式开发

    零基础ASP.NET Core MVC插件式开发 一个项目随着业务模块的不断增加,系统会越来越庞大.如果参与开发的人员越多,管理起来也难度也很大.面对这样的情况,首先想到的是模块化插件式开发,根据业务 ...

  10. web文件下载(附方案及源码配置)

    1. 场景描述 因项目需查询数据量比较大(需要查询Hbase等nosql数据库),采用用户点击查询后,后台查询并生成查询文件:然后消息通知用户后,用户点击下载的方式来满足用户需求. 2. 解决方案 W ...