200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > vue+elementUI实现自定义表单模板组件(一)

vue+elementUI实现自定义表单模板组件(一)

时间:2021-06-29 21:09:52

相关推荐

vue+elementUI实现自定义表单模板组件(一)

前言

如下图,实现一个可以自定义的表单。本文以实现思路为主,并未提供完整代码。

思路

1、页面布局为左中右布局:左边显示可以定义的表单控件,中间显示预览效果,右边则为选中某个控件后可以编辑的属性。如下图,先择单选项后,可以编辑选项。

2、使用 vuedraggable 拖拽组件,直接拖动左边的控件到中间生成表单。vuedraggable 文档可查阅:

/SortableJS/Vue.Draggable

(你也可以不使用该组件,直接利用点击事件,点击左边控件后在中间生成表单)

主要实现

以文本和选项为例,其他控件可自行拓展。

html 部分

<template><div><el-row :gutter="20"><el-col :span="3"><h4>基础控件</h4><draggable :options="dragOptions" v-model="compList" @end="end1" :move="onMove1"><div v-for="(item, index) in compList" :key="index" class="comp-item pointer"><i :class="item.icon"></i>{{item.label}}</div></draggable></el-col><el-col :span="16" style="border-left:1px solid #DCDFE6;border-right:1px solid #DCDFE6"><el-row><el-col :span="12"><h4>表单内容</h4></el-col></el-row><template v-if=" 0 == (formList &&formList.length)"><divstyle="line-height: 50px;height: 50px;border: 1px dashed #d9d9d9;padding-left:20px;margin-top:10px">拖动左边的控件进行自定义字段编辑</div></template><draggablestyle="height:calc(100vh - 220px);overflow-y:auto"group="comp"v-model="formList"@start="start2"@end="end2":move="onMove2"><divclass="temp-content"@click="activeIndex=index":class="activeIndex==index?'temp-active':''"v-for="(item, index) in formList":key="index"><div style="padding:10px"><el-row><el-col :span="20"><inputplaceholder="请输入字段标题,8个字内"maxlength="8"v-model="item.label"style="border:none;width:100%;outline: none;"/></el-col><el-col :span="3" class="text-right pointer"><template v-if="activeIndex==index"><i class="el-icon-delete text-red" title="删除" @click.stop="delItem(index)"></i></template></el-col></el-row></div><div><!-- 单选 --><template v-if="item.type=='radio'"><el-radio-group disabled><el-radio v-for="(it, idx) in item.options" :key="idx" :label="idx">{{it}}</el-radio></el-radio-group></template><!-- 多选 --><template v-else-if="item.type=='checkbox'"><el-checkbox-group disabled><el-checkbox v-for="(it, idx) in item.options" :key="idx" :label="idx">{{it}}</el-checkbox></el-checkbox-group></template><template v-else><el-input disabled :placeholder="item.placeholder?item.placeholder:'待填写者输入'"></el-input></template></div></div></draggable></el-col><el-col :span="5"><template v-if="formList&&formList.length>0"><h4><i :class="formList[activeIndex].icon"></i>{{formList[activeIndex].typeName}}</h4><el-form style="margin-top:10px" label-suffix=":"><el-form-item label="标题"><el-input v-model="formList[activeIndex].label"></el-input></el-form-item><!-- 图片附件不显示 --><templatev-if="formList[activeIndex].type != 'radio' && formList[activeIndex].type != 'checkbox' && formList[activeIndex].type != 'file' && formList[activeIndex].type != 'rate' "><el-form-item label="提示文字"><el-input v-model="formList[activeIndex].placeholder"></el-input></el-form-item></template><!-- 选项 --><templatev-if="formList[activeIndex].type == 'radio' || formList[activeIndex].type == 'checkbox'"><el-form-item label="选项"><el-rowstyle="margin-top:10px"v-for="(item, index) in formList[activeIndex].options":key="index"><el-col :span="22"><el-input v-model="formList[activeIndex].options[index]"></el-input></el-col><el-col :span="2" class="text-center"><i class="el-icon-delete text-red" @click="delOption(index)"></i></el-col></el-row><div style="margin-top:10px"><el-button type="text" @click="addOption">添加选项</el-button></div></el-form-item></template><el-form-item label="必填"><el-switch v-model="formList[activeIndex].required"></el-switch></el-form-item></el-form></template></el-col></el-row></div></template>

script 部分

<script>export default {name: 'formBuilder',props: {templateHtml: {type: String,default: '' // 初始化}},data() {return {activeIndex: 0, // 当前编辑的 indexfutureIndex: 0, // 插入的数组 indexisRight: false, // 是否拖动到右边formList: [],dragOptions: {group: {name: 'comp', pull: 'clone' }, sort: true },compList: [{label: '单选项',icon: 'el-icon-s-tools',type: 'radio'},{label: '多选项',icon: 'el-icon-s-tools',type: 'checkbox'},{label: '文本',icon: 'el-icon-document-remove',type: 'text'}]}},mounted() {this.renderForm(this.templateHtml)},watch: {templateHtml(newVal) {this.renderForm(newVal)}},methods: {renderForm(newVal) {if (newVal == '[]' || newVal == '' || newVal == null) {this.formList = []} else {this.formList = JSON.parse(newVal)}},// 获取字段数据getFields() {if (0 == this.formList.length) {this.$message.error('必须增加模板字段!')return false}let pass = truelet formList = this.formListfor (let i = 0; i < formList.length; i++) {formList[i]._vModel = 'field' + iif (!formList[i].label) {this.$message.error('请输入字段标题!')pass = falsebreak}}//if (pass) {return this.formList} else {return false}},// 新增选项addOption() {let idx = this.formList[this.activeIndex].options.length + 1this.formList[this.activeIndex].options.push('选项' + idx)},// 删除选项delOption(index) {this.formList[this.activeIndex].options.splice(index, 1)},// 删除模板字段delItem(index) {this.formList.splice(index, 1)let leg = this.formList.lengthif (leg == index && leg > 0) {this.activeIndex = index - 1}},// 根据类型获取字段getFormByType(data) {let item = {label: data.label,required: false,type: data.type,icon: data.icon,typeName: data.label,placeholder: ''}// 是否选项if (data.type == 'radio' || data.type == 'checkbox') {item.options = ['选项1', '选项2', '选项3']}return item},end1(e) {if (this.isRight) {let data = this.getFormByType(pList[e.oldIndex])this.formList.splice(this.futureIndex, 0, data)this.activeIndex = this.futureIndex}},start2(e) {},end2(e) {// 判断移动的项目是否为编辑行if (e.oldIndex != e.newIndex && this.activeIndex == e.oldIndex) {this.activeIndex = e.newIndex}},onMove1(e, originalEvent) {this.futureIndex = e.draggedContext.futureIndexif (ponent.$attrs.group == 'comp') {this.isRight = true} else {this.isRight = false}return false},onMove2(e, originalEvent) {if (ponent.$attrs.group == 'comp') {return true} else {return false}}}}</script>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。