【工作小tip】elementUI表单嵌套增删

25 篇文章 0 订阅
23 篇文章 0 订阅

因为工作业务需要,所以要做个带有嵌套增删效果的表格,公司项目用的elementUI,所以是elementUI做的

elementUI表单嵌套增删

在这里插入图片描述

数据初始化
data() {
			return {
				form: {
					categoryItem: [
					],
				},
			}
},
表格原型
<sp-form-group v-model="isCollapse['categoryItem']" name="分类标准" :add="isEdit"
	:clear="form.categoryItem && form.categoryItem.length > 1 && form.categoryItem.filter(row => row.isDeleted !== 1).length > 1  && isEdit" @add="clickCategoryItemAdd()" @clear="clearSub(form.categoryItem, '分类标准')">
	<ul class="form-group-list">
		<template v-for="(subItem, subIdx) in form.categoryItem || []">
			<li v-if="subItem.isDeleted != 1" :key="subIdx" class="form-group-list-item"
				style="background: #f2f3f5">
				<div style="flex: 1;">
					<el-row :gutter="24">
						<el-col :md="12" :lg="12" :xl="12">
							<el-form-item label="标准分类" :required="true"
								:prop="'categoryItem.' + subIdx + '.itemName'"
								:rules="ruleForm.categoryItem.itemName">
								<sp-select v-model="subItem.itemName" :maxlength="255"
									placeholder="请选择分类" :readonly="isView" />
								<el-button icon="el-icon-plus" @click="clickCategoryItemAdd()"></el-button>
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="24">
						<el-col :md="4" :lg="4" :xl="4">
							<el-form-item>
								<el-button type="primary">添加分类项</el-button>
							</el-form-item>
						</el-col>
						<el-col :md="10" :lg="10" :xl="10">
							<el-form-item
								:prop="'categoryItem.' + subIdx + '.itemName'"
								:rules="ruleForm.categoryItem.itemName">
								<sp-text v-model="subItem.itemName" placeholder="请输入分类项目"
									:maxlength="10" :precision="0" :size="formSize"
									:readonly="isView" />
								</el-form-item>
						</el-col>
						<el-col :md="10" :lg="10" :xl="10">
							<el-form-item
								:prop="'categoryItem.' + subIdx + '.score'"
								:rules="ruleForm.categoryItem.score">
								<sp-text v-model="subItem.score" :maxlength="10" placeholder="请输入分值" :readonly="isView" />
							</el-form-item>
						</el-col>
					</el-row>
				<div v-for="(item, i) in form.categoryItem[subIdx].standards || []">
					<el-row :gutter="24" :key="i">	
						<el-col :md="4" :lg="4" :xl="4">
							<el-form-item>
							</el-form-item>
						</el-col>
													
						<el-col :md="20" :lg="20" :xl="20">
							<el-form-item>
								<sp-text v-model="item.standard" :data-list="[]" :maxlength="50" :readonly="isView" style="width:86%" placeholder="请输入标准"/>
								<el-button circle icon="el-icon-delete" @click="clickStandardItemDel(subIdx, subItem, i)" style="margin: 0%;"></el-button>
								<el-button circle icon="el-icon-plus" @click="clickStandardItemAdd(subIdx)" style="margin: 0%;"></el-button>
							</el-form-item>
						</el-col>
					</el-row>	
				</div>
			</div>
             <el-popconfirm placement="top-end" title="确定删除该条子表信息?" @confirm="clickCategoryItemDel(subItem, subIdx)">
				<el-link slot="reference" type="danger" style="margin-left: 30px;">删除
				</el-link>
			</el-popconfirm>
		</li>
	</template>
</ul>
</sp-form-group>
添加和删除一份标准分类表格
//控制标准分类增删
			clickCategoryItemAdd() {
				this.form.categoryItem.unshift({
					itemName: undefined,
					score: undefined,
					standards: [
						{ standard:undefined,standardTypeId: undefined,standardType: undefined }
					],
					templateId: undefined,
					parkId: undefined,
				})
			},
			
			clickCategoryItemDel(row, idx) {
				if (row.id) {
					row.isDeleted = 1
				} else {
					this.form.categoryItem.splice(idx, 1)
				}
			},
一行标准输入框的原型(嵌套所在)
				<div v-for="(item, i) in form.categoryItem[subIdx].standards || []">
					<el-row :gutter="24" :key="i">	
						<el-col :md="4" :lg="4" :xl="4">
							<el-form-item>
							</el-form-item>
						</el-col>
													
						<el-col :md="20" :lg="20" :xl="20">
							<el-form-item>
								<sp-text v-model="item.standard" :data-list="[]" :maxlength="50" :readonly="isView" style="width:86%" placeholder="请输入标准"/>
								<el-button circle icon="el-icon-delete" @click="clickStandardItemDel(subIdx, subItem, i)" style="margin: 0%;"></el-button>
								<el-button circle icon="el-icon-plus" @click="clickStandardItemAdd(subIdx)" style="margin: 0%;"></el-button>
							</el-form-item>
						</el-col>
					</el-row>	
				</div>
添加和删除一行标准输入框(注意因为标准输入框嵌套在表格里,因此添加输入框是在表格里面的standards里加上对应属性)
			//控制标准输入框增删
			clickStandardItemAdd(subIdx) {
				this.form.categoryItem[subIdx].standards.unshift({
					standard:'',
					standardTypeId: '',
					standardType: '',
				})
			},
			clickStandardItemDel(subIdx, row, idx) {
				if (row.id) {
					row.isDeleted = 1
				} else {
					this.form.categoryItem[subIdx].standards.splice(idx, 1)
				}
			},
所有代码
<template>
	<component :is="componentName" v-if="isDialog ? dialog.visible : true" :visible.sync="dialog.visible"
		v-loading="formModel ? false : fullLoading" v-bind="dynamicAttr">
		<div class="detailForm" :style="formModel === 'drawer' ? 'padding: 0px 32px 128px;' : ''">
			<section>
				<header v-if="!isDialog" class="spui-header">
					<span class="spui-header-title">{{title}}</span>
					<div>
						<el-button v-if="isEdit" type="primary" size="small" :loading="btnLoading" @click="onSubmit()">
							完成</el-button>
						<el-button size="small" :loading="btnLoading" @click="back()">返回</el-button>
					</div>
				</header>
				<main class="e-main">
					<el-form ref="ruleForm" class="spui-form" 
						:class="isView ? 'spui-form-view' : ''" 
						:model="form"
						:rules="isEdit ? ruleForm : null" 
						label-width="130px" 
						:size="formSize" 
						label-position="top"
						@submit.native.prevent v-loading="fullLoading">
						<sp-form-group v-model="isCollapse['base']" name="基本信息" :border="true">
							<el-row :gutter="24">
								<el-col :md="12" :lg="12" :xl="12">
									<el-form-item label="模板名称1" prop="templateName">
										<sp-text v-model="form.templateName" :maxlength="255" placeholder="请输入模板名称"
											:readonly="isView" />
									</el-form-item>
								</el-col>
								
								<el-col :md="12" :lg="12" :xl="12">
									<el-form-item label="模板属性" prop="attribute">
										<sp-numeric v-model="form.attribute" placeholder="请输入模板属性(0:总部1:大区)"
											:maxlength="11" :precision="0" :size="formSize" :readonly="isView" />
									</el-form-item>
								</el-col>
							</el-row>
							<el-row :gutter="24">
								<el-col :md="12" :lg="12" :xl="12">
									<el-form-item label="模板类型" prop="type">
										<sp-select v-model="form.type" :data-list="[]" :readonly="isView" placeholder="请选择类型"
											style="width:100%" />
									</el-form-item>
								</el-col>
								<el-col :md="12" :lg="12" :xl="12">
									<el-form-item label="权重占比" prop="proportionOfWeight">
										<sp-numeric v-model="form.proportionOfWeight" placeholder="请输入权重占比"
											:maxlength="11" :precision="0" :size="formSize" :readonly="isView" />
									</el-form-item>
								</el-col>
							</el-row>
							<el-row :gutter="24">
								<el-col :span="24">
								  <el-form-item label="备注" prop="">
								    <el-input
								      type="textarea"
								      :autosize="{ minRows: 4 }"
								      size="small"
								      placeholder="请输入备注"
								      maxlength="256"
								      show-word-limit
								    ></el-input>
								  </el-form-item>
								</el-col>
							</el-row>
							
						</sp-form-group>
						<sp-form-group v-model="isCollapse['categoryItem']" name="分类标准" :add="isEdit"
							:clear="form.categoryItem && form.categoryItem.length > 1 && form.categoryItem.filter(row => row.isDeleted !== 1).length > 1  && isEdit"
							@add="clickCategoryItemAdd()" @clear="clearSub(form.categoryItem, '分类标准')">
							<ul class="form-group-list">
								<template v-for="(subItem, subIdx) in form.categoryItem || []">
									<li v-if="subItem.isDeleted != 1" :key="subIdx" class="form-group-list-item"
										style="background: #f2f3f5">
										<div style="flex: 1;">
											<el-row :gutter="24">
												<el-col :md="12" :lg="12" :xl="12">
													<el-form-item label="标准分类" :required="true"
														:prop="'categoryItem.' + subIdx + '.itemName'"
														:rules="ruleForm.categoryItem.itemName">
														<sp-select v-model="subItem.itemName" :maxlength="255"
															placeholder="请选择分类" :readonly="isView" />
														<el-button icon="el-icon-plus" @click="clickCategoryItemAdd()"></el-button>
													</el-form-item>
												</el-col>
											</el-row>
											
											
											
											<el-row :gutter="24">
												<el-col :md="4" :lg="4" :xl="4">
													<el-form-item>
														<el-button type="primary" @click="clickCategoryItemAdd()">添加分类项</el-button>
													</el-form-item>
												</el-col>
												<el-col :md="10" :lg="10" :xl="10">
													<el-form-item
														:prop="'categoryItem.' + subIdx + '.itemName'"
														:rules="ruleForm.categoryItem.itemName">
														<sp-text v-model="subItem.itemName" placeholder="请输入分类项目"
															:maxlength="10" :precision="0" :size="formSize"
															:readonly="isView" />
													</el-form-item>
												</el-col>
												<el-col :md="10" :lg="10" :xl="10">
													<el-form-item
														:prop="'categoryItem.' + subIdx + '.score'"
														:rules="ruleForm.categoryItem.score">
														<sp-text v-model="subItem.score" :maxlength="10"
															placeholder="请输入分值" :readonly="isView" />
													</el-form-item>
												</el-col>
											</el-row>
											<div v-for="(item, i) in form.categoryItem[subIdx].standards || []">
												<el-row :gutter="24" :key="i">	
													<el-col :md="4" :lg="4" :xl="4">
														<el-form-item>
														</el-form-item>
													</el-col>
													
													<el-col :md="20" :lg="20" :xl="20">
														<el-form-item>
															<sp-text v-model="item.standard" :data-list="[]" :maxlength="50"
																:readonly="isView" style="width:86%" placeholder="请输入标准"/>
															<el-button circle icon="el-icon-delete" @click="clickStandardItemDel(subIdx, subItem, i)" style="margin: 0%;"></el-button>
															<el-button circle icon="el-icon-plus" @click="clickStandardItemAdd(subIdx)" style="margin: 0%;"></el-button>
														</el-form-item>
													</el-col>
												</el-row>	
											</div>
											
										</div>
										<el-popconfirm placement="top-end" title="确定删除该条子表信息?"
											@confirm="clickCategoryItemDel(subItem, subIdx)">
											<el-link slot="reference" type="danger" style="margin-left: 30px;">删除
											</el-link>
										</el-popconfirm>
									</li>
								</template>
							</ul>
						</sp-form-group>
					</el-form>
				</main>
			</section>
		</div>
		<div v-if="isDialog"
			v-bind="formModel == 'dialog' ? { slot: 'footer' } : { slot: 'title', style: 'display: flex; justify-content: space-between; align-items: center;' }">
			<span v-if="formModel == 'drawer'" style="font-size: 20px; color: #1d2129;">{{ title }}</span>
			<span>
				<el-button size="small" @click="back">取 消</el-button>
				<el-button v-if="params.state !== 'view'" size="small" type="primary" @click="onSubmit"
					:loading="btnLoading">确 定</el-button>
			</span>
		</div>
	</component>
</template>

<script>
	import {
		AppraisalTemplateApi
	} from '@/api/module/appraisalTemplate/appraisal.template.js'

	export default {
		props: {
			dialog: {
				type: Object,
				default: () => {
					return {}
				},
			},
			formModel: {
				type: String,
			},
		},
		components: {},
		data() {
			let isDialog = (this.dialog.visible != undefined && this.formModel) || false
			return {
				// 判断是否为弹窗
				isDialog: isDialog,
				params: isDialog ? this.dialog : this.$route.query,
				isFormChange: false,
				fullLoading: false,
				btnLoading: false,
				formSize: 'small',
				ruleForm: {
					categoryItem: {},
				},
				form: {
					templateName: undefined,
					type: undefined,
					attribute: undefined,
					proportionOfWeight: undefined,
					parkId: undefined,
					status: undefined,
					categoryItem: [
					],
					
				},
				
				// 折叠
				isCollapse: {
					base: true,
					categoryItem: false,
				},
			}
		},
		computed: {
			componentName() {
				const n = {
					default: 'sp-container',
					dialog: 'p-dialog',
					drawer: 'el-drawer',
				}
				return n[this.formModel || 'default']
			},
			// 动态属性
			dynamicAttr() {
				const attrData = {
					default: {
						background: '#f2f3f5',
						block: true,
						style: 'min-height: 100vh',
					},
					dialog: {
						title: this.title,
						width: '80vw',
						'max-width': '860px',
						'before-close': this.back,
						'append-to-body': true,
					},
					drawer: {
						title: this.title,
						size: '60vw',
						'before-close': this.back,
						'append-to-body': true,
						'show-close': false,
						wrapperClosable: false,
					},
				}
				return attrData[this.formModel || 'default']
			},
			// 判断是否为新增
			isAdd() {
				return this.params.state === 'add' || !this.params.state
			},
			// 判断是否为新增或修改
			isEdit() {
				return this.params.state !== 'view'
			},
			// 判断是否为新增或修改
			isView() {
				return this.params.state === 'view'
			},
			title() {
				return '考核模板' + (this.isAdd ? '新增' : this.isEdit ? '修改' : '查看')
			}
		},
		created() {},
		mounted() {
			if (this.isAdd && this.params.parkId) {
				this.form.parkId = this.params.parkId
			}
			this.loadData()
		},
		methods: {
			loadData() {
				if (!this.isAdd) {
					this.fullLoading = true
					this.btnLoading = true
					AppraisalTemplateApi.get(this.params.id).then((res) => {
						const data = res.data
						data.categoryItem = data.categoryItem || []
						this.form = data
					}).finally(() => {
						this.fullLoading = false
						this.btnLoading = false
					})
				}
			},
			onSubmit() {
				this.$refs.ruleForm.validate(valid => {
					if (valid) {
						this.fullLoading = true
						this.btnLoading = true
						let apiMethod = this.isAdd ? AppraisalTemplateApi.add : AppraisalTemplateApi.update
						apiMethod(this.form).then((res) => {
							if (res.success) {
								this.$notify({
									type: 'success',
									message: '保存成功',
									title: '提示',
								})
								this.isFormChange = true
								this.back()
							}
						}).finally(() => {
							this.fullLoading = false
							this.btnLoading = false
						})
					} else {
						// TODO 表单验证未通过处理
					}
				})
			},
			clearSub(sub, title) {
				this.$confirm('确定清空' + title + '吗?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning',
				}).then(() => {
					for (let i = 0, len = sub.length; i < len; i++) {
						if (sub[i].id) {
							sub[i].isDeleted = 1
						} else {
							sub.splice(i, 1)
							i--
							len--
						}
					}
				})
			},
			//控制标准输入框增删
			clickStandardItemAdd(subIdx) {
				this.form.categoryItem[subIdx].standards.unshift({
					standard:'',
					standardTypeId: '',
					standardType: '',
				})
			},
			clickStandardItemDel(subIdx, row, idx) {
				if (row.id) {
					row.isDeleted = 1
				} else {
					this.form.categoryItem[subIdx].standards.splice(idx, 1)
				}
			},
			//控制标准分类增删
			clickCategoryItemAdd() {
				this.form.categoryItem.unshift({
					itemName: undefined,
					score: undefined,
					standards: [
						{ standard:undefined,standardTypeId: undefined,standardType: undefined }
					],
					templateId: undefined,
					parkId: undefined,
				})
			},
			
			clickCategoryItemDel(row, idx) {
				if (row.id) {
					row.isDeleted = 1
				} else {
					this.form.categoryItem.splice(idx, 1)
				}
			},
			// 子表操作 end
			back() {
				if (this.isDialog) {
					if (this.isFormChange) {
						this.$emit('updateList')
					}
					this.$emit('update:dialog', {
						...this.dialog,
						visible: false
					})
				} else {
					let router = {
						path: '/appraisal-template',
					}
					this.$router.push(router)
				}
			},
		}
	}
</script>
<style lang="less" scoped>
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值