Vue3+Element-Plus使用el-form和el-table嵌套实现表格编辑并提交表单校验

发布于:2024-12-18 ⋅ 阅读:(312) ⋅ 点赞:(0)

el-form和el-table嵌套说明

① :model="formData" 给表单绑定数据,formData是表单的数据对象

② 表单数据对象formData中定义的tableData是表单内嵌套的表格显示数据

③ rules为表单绑定的校验规则

④ :prop="`tableData.${$index}.name`" 绑定传入Form 组件的 model 中对应的字段name

⑤ :rules="rules.name" 绑定表单校验规则

⑥ 整个html结构是一个大表单 el-form里边嵌套的el-table,而el-table中又嵌套了表单项 el-form-item支持编辑。

备注:大多情况下prop会按照惯有思维直接写入字段,而这里是动态绑定的,另外一定要记得每项动态写入rules来进行绑定表单校验 

具体代码

<template>
	<div class="layout-padding">
		<div class="layout-padding-auto" style="background-color: #fff;">
			<el-form :model="formData" ref="formRef" :rules="rules" :inline="true">
				<el-table :data="formData.tableData" border>
					<el-table-column type="index" align="center" label="序号" width="65">
					</el-table-column>
					<el-table-column label="姓名" prop="name" resizable align="center" header-align="center">
						<template #default="{ row, $index }">
							<el-form-item :prop="`tableData.${$index}.name`" :rules="rules.name">
								<el-input type="text" placeholder="请输入姓名" v-model="row.name"></el-input>
							</el-form-item>
						</template>
					</el-table-column>
					<el-table-column label="年龄" prop="age" resizable align="center" header-align="center">
						<template #default="{ row, $index }">
							<el-form-item :prop="`tableData.${$index}.age`" :rules="rules.age">
								<el-input type="text" placeholder="请输入年龄" v-model="row.age"></el-input>
							</el-form-item>
						</template>
					</el-table-column>
					<el-table-column label="性别" prop="sex" resizable align="center" header-align="center">
						<template #default="{ row, $index }">
							<el-form-item :prop="`tableData.${$index}.sex`" :rules="rules.sex">
								<el-input type="text" placeholder="请输入性别" v-model="row.sex"></el-input>
							</el-form-item>
						</template>
					</el-table-column>
					<el-table-column label="操作" resizable align="center" header-align="center" width="200">
						<template #default="{ row, $index }">
							<el-button type="primary" icon="ele-Plus" circle @click="addTable()"
								v-if="$index == 0"></el-button>
							<el-button icon="ele-Minus" circle @click="delTable($index)" v-else></el-button>
						</template>
					</el-table-column>
				</el-table>
				<el-form-item class="footer">
					<el-button @click="reset">重置</el-button>
					<el-button type="primary" @click="save">保存</el-button>
				</el-form-item>
			</el-form>
		</div>
	</div>
</template>
   
<script lang="ts">
import { toRefs, reactive, defineComponent, getCurrentInstance, } from 'vue';

export default defineComponent({
	setup() {
		const { proxy }: any = getCurrentInstance();

		const data = reactive({
			formData: {
				tableData: [
					{ name: '张三', age: 18, sex: '' },
					{ name: '李四', age: 19, sex: '' },
				] as any[]
			},
			rules: {
				name: [
					{ required: true, message: '请输入姓名', trigger: 'blur' },
				],
				age: [
					{ required: true, message: '请输入年龄', trigger: 'blur' },
				],
				sex: [
					{ required: true, message: '请输入性别', trigger: 'blur' },
				],
			}
		});

		//保存
		const save = () => {
			//第一条数据不进行校验
			if (data.formData.tableData.length == 1 &&
				data.formData.tableData[0].name == '' &&
				data.formData.tableData[0].age == '' &&
				data.formData.tableData[0].sex == '') {
				//将rules中的校验required设置为false
				data.rules.name[0].required = false;
				data.rules.age[0].required = false;
				data.rules.sex[0].required = false;
			} else {
				//如果不是第一条数据,将rules中的校验required设置为true进行校验
				data.rules.name[0].required = true;
				data.rules.age[0].required = true;
				data.rules.sex[0].required = true;
			}

			proxy.$refs.formRef.validate((valid: any) => {
				//如果valid为true,表示校验通过,可以提交表单,调取接口进行保存
				if (valid) {
					proxy.$message.success("保存成功");
				} else {
					proxy.$message.warning("请填写完整的数据");
				}
			})
		}

		//重置
		const reset = () => {
			proxy.$refs.formRef.resetFields()
			data.formData.tableData = [
				{ name: '张三', age: 18, sex: '' },
				{ name: '李四', age: 19, sex: '' },
			]
		}

		//添加
		const addTable = () => {
			let newArr = [
				{
					name: '',
					age: '',
					sex: ''
				}
			]
			data.formData.tableData.push(...newArr)
		}

		//删除
		const delTable = (i: number) => {
			data.formData.tableData.splice(i, 1)
		}

		return {
			...toRefs(data), save, reset, addTable, delTable
		};
	}
})
</script>
   
<style lang="scss" scoped>
.footer {
	width: 100%;
	margin-top: 50px;

	:deep(.el-form-item__content) {
		justify-content: center;
	}
}
</style>

效果图


网站公告

今日签到

点亮在社区的每一天
去签到