目录
一、背景
二、功能实现
2.1、el-form和el-table嵌套说明
2.2、具体代码
三、实际项目应用
3.1、增加添加与删除操作
3.2、添加和删除代码
3.3、完整代码
3.4、实际效果
四、需求拓展
4.1、需求描述
4.2、需求分析
4.2.1、描述:
4.2.2、场景:
4.2.3、思路:
4.3、代码实现
4.4、效果展示
一、背景
页面需要用到表格采集用户数据,提交时进行表单校验;即表单中嵌套着表格,保存时进行表单校验
二、功能实现
2.1、el-form和el-table嵌套说明
① :model="formData" 给表单绑定数据,formData是表单的数据对象
② 表单数据对象formData中定义的tableData是表单内嵌套的表格显示数据
③ rules为表单绑定的校验规则
④ :prop="'tableData.' + scope.$index + '.name'" 绑定传入Form 组件的 model 中对应的字段name
⑤ :rules="rules.name" 绑定表单校验规则
⑥ 整个html结构是一个大表单 el-form里边嵌套的el-table,而el-table中又嵌套了表单项 el-form-item支持编辑。
备注:大多情况下prop会按照惯有思维直接写入字段,而这里是动态绑定的,另外一定要记得每项动态写入rules来进行绑定表单校验
2.2、具体代码
<template> <div> <el-form :model="formData" ref="formRef" :rules="rules" label-width="108px" :inline="true" > <el-table :data="formData.tableData" style="width: 100%" border > <el-table-column type="index" width="55" align="center"> </el-table-column> <el-table-column label="姓名" prop="name" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.name'" :rules="rules.name"> <el-input type="text" size="small" placeholder="请输入姓名" v-model="scope.row.name"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="年龄" prop="age" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.age'" :rules="rules.age"> <el-input type="text" size="small" placeholder="请输入年龄" v-model="scope.row.age"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="性别" prop="sex" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.sex'" :rules="rules.sex"> <el-input type="text" size="small" placeholder="请输入性别" v-model="scope.row.sex"></el-input> </el-form-item> </template> </el-table-column> </el-table> <el-form-item class="footer"> <el-button type="primary" @click="save">保存</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </div> </template> <script> export default{ data(){ return{ formData:{ tableData:[ {name:'张三',age:18,sex:''}, {name:'李四',age:19,sex:''}, ] }, rules:{ name:[ { required: true, message: '请输入姓名', trigger: 'blur' }, ], age:[ { required: true, message: '请输入年龄', trigger: 'blur' }, ], sex:[ { required: true, message: '请输入性别', trigger: 'blur' }, ], } } }, methods:{ //保存 save(){ this.$refs.formRef.validate((valid) => { console.log('valid',valid); if(valid){ //如果valid为true,表示校验通过,可以提交表单,调取接口进行保存 console.log('表单校验通过'); }else { this.$message.warning("请填写完整的数据"); } }) }, } } </script> <style lang="scss" scoped> .footer{ margin-top: 50px; } </style>
复制
三、实际项目应用
3.1、增加添加与删除操作
需求:表格增加操作项,具有添加和删除按钮,第一项无法删除,点击添加时,动态增加表格的行数,点击删除的时候,删除表格的行数据。
3.2、添加和删除代码
结构:直接添加一个表格项
<el-table-column label="操作" resizable align="center" header-align="center"> <template slot-scope="{$index}"> <el-button type="primary" icon="el-icon-plus" circle @click="addTable()" v-if="$index == 0"></el-button> <el-button icon="el-icon-minus" circle @click="delTable($index)" v-if="$index > 0"></el-button> </template> </el-table-column>
复制
methods:{ //添加 addTable(){ let newArr = [ { name:'', age:'', sex:'' } ] this.formData.tableData.push(...newArr) }, //删除 delTable(i){ this.formData.tableData.splice(i,1) } }
复制
3.3、完整代码
<template> <div> <el-form :model="formData" ref="formRef" :rules="rules" label-width="108px" :inline="true" > <el-table :data="formData.tableData" style="width: 100%" border > <el-table-column type="index" width="55" align="center"> </el-table-column> <el-table-column label="姓名" prop="name" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.name'" :rules="rules.name"> <el-input type="text" size="small" placeholder="请输入姓名" v-model="scope.row.name"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="年龄" prop="age" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.age'" :rules="rules.age"> <el-input type="text" size="small" placeholder="请输入年龄" v-model="scope.row.age"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="性别" prop="sex" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.sex'" :rules="rules.sex"> <el-input type="text" size="small" placeholder="请输入性别" v-model="scope.row.sex"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="操作" resizable align="center" header-align="center"> <template slot-scope="{$index}"> <el-button type="primary" icon="el-icon-plus" circle @click="addTable()" v-if="$index == 0"></el-button> <el-button icon="el-icon-minus" circle @click="delTable($index)" v-if="$index > 0"></el-button> </template> </el-table-column> </el-table> <el-form-item class="footer"> <el-button type="primary" @click="save">保存</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </div> </template> <script> export default{ data(){ return{ formData:{ tableData:[ {name:'张三',age:18,sex:'男'}, {name:'李四',age:19,sex:''}, ] }, rules:{ name:[ { required: true, message: '请输入姓名', trigger: 'blur' }, ], age:[ { required: true, message: '请输入年龄', trigger: 'blur' }, ], sex:[ { required: true, message: '请输入性别', trigger: 'blur' }, ], } } }, methods:{ //保存 save(){ this.$refs.formRef.validate((valid) => { console.log('valid',valid); if(valid){ //如果valid为true,表示校验通过,可以提交表单,调取接口进行保存 console.log('表单校验通过'); this.$message.success("保存成功"); }else { this.$message.warning("请填写完整的数据"); } }) }, //添加 addTable(){ let newArr = [ { name:'', age:'', sex:'' } ] this.formData.tableData.push(...newArr) }, //删除 delTable(i){ this.formData.tableData.splice(i,1) } } } </script> <style> .footer{ margin-top: 50px; } </style>
复制
3.4、实际效果
四、需求拓展
4.1、需求描述
背景:页面中包含2个功能设置区,当用户进行操作后,统一进行保存,如下👇
①功能模块设置区:👉 可以进行排序和多选框选中操作,
②功能模块自定义设置区:👉 用户可以根据需求自定义设置,操作或不操作
页面排版大致如下👇
4.2、需求分析
4.2.1、描述:
自定义设置区默认要有一条空数据在页面展示,可供用户自定义操作,不管用户是否填写,保存时都能正常保存,如果用户填写了表单但不完整,此时需对表单进行校验通过再保存成功
4.2.2、场景:
用户只对模块设置区的排序或多选框进行了操作,没有对自定义设置区进行操作就保存,因对自定义设置区的表单进行了校验,此时无法提交,需更改现有代码;其中第一条数据也可以进行删除
4.2.3、思路:
默认对表格中第一条表单不校验,如果表单填写了但不完整就需要校验,保存成功后,页面展示接口中的数据;如果删除后只剩第一条数据,第一条数据删除后push一条空数据在页面展示,可供用户进行自定义操作
4.3、代码实现
<template> <div> <el-form :model="formData" ref="formRef" :rules="rules" label-width="108px" :inline="true" > <el-table :data="formData.tableData" style="width: 100%" border > <el-table-column type="index" width="55" align="center"> </el-table-column> <el-table-column label="姓名" prop="name" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.name'" :rules="rules.name"> <el-input type="text" size="small" placeholder="请输入姓名" v-model="scope.row.name"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="年龄" prop="age" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.age'" :rules="rules.age"> <el-input type="text" size="small" placeholder="请输入年龄" v-model="scope.row.age"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="性别" prop="sex" resizable align="center" header-align="center"> <template slot-scope="scope"> <el-form-item :prop="'tableData.' + scope.$index + '.sex'" :rules="rules.sex"> <el-input type="text" size="small" placeholder="请输入性别" v-model="scope.row.sex"></el-input> </el-form-item> </template> </el-table-column> <el-table-column label="操作" resizable align="center" header-align="center"> <template slot-scope="{$index}"> <el-button type="primary" icon="el-icon-plus" circle @click="addTable()" v-if="$index == 0"></el-button> <el-button icon="el-icon-minus" circle @click="delTable($index)"></el-button> </template> </el-table-column> </el-table> <el-form-item class="footer"> <el-button type="primary" @click="save">保存</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </div> </template> <script> export default{ data(){ return{ formData:{ tableData:[ {name:'',age:'',sex:''}, ] }, rules:{ name:[ { required: true, message: '请输入姓名', trigger: 'blur' }, ], age:[ { required: true, message: '请输入年龄', trigger: 'blur' }, ], sex:[ { required: true, message: '请输入性别', trigger: 'blur' }, ], } } }, methods:{ //保存 save(){ //第一条数据不进行校验 if(this.formData.tableData.length == 1 && this.formData.tableData[0].name == '' && this.formData.tableData[0].age == '' && this.formData.tableData[0].sex == ''){ //将rules中的校验required设置为false this.rules.name[0].required = false; this.rules.age[0].required = false; this.rules.sex[0].required = false; }else{ //如果不是第一条数据,将rules中的校验required设置为true进行校验 this.rules.name[0].required = true; this.rules.age[0].required = true; this.rules.sex[0].required = true; } this.$refs.formRef.validate((valid) => { console.log('valid',valid); if(valid){ this.$message.success("保存成功"); //如果valid为true,表示校验通过,可以提交表单,调取接口进行保存 console.log('表单校验通过'); }else { this.$message.warning("请填写完整的数据"); } }) }, //添加 addTable(){ let newArr = [ { name:'', age:'', sex:'' } ] this.formData.tableData.push(...newArr) }, //删除 delTable(i){ this.formData.tableData.splice(i,1) //如果删除的是第一条,再push一条空数据在页面 if(i === 0){ this.formData.tableData.push({ name:'', age:'', sex:'' }) } } } } </script> <style> .footer{ margin-top: 50px; } </style>
复制
4.4、效果展示
图①:表格中展示一条空数据可自定义设置,如果没操作也可以正常保存,不做校验
图②:如果已填写表单但数据不完整,保存时对表单进行校验
图③:当只剩最后一条数据时,点击删除按钮再push一条空数据在页面进行展示
最后:👏👏 😀😀😀 👍👍