【Element】el-form和el-table嵌套实现表格编辑并提交表单校验

目录

一、背景

二、功能实现

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一条空数据在页面进行展示

最后:👏👏 😀😀😀 👍👍   

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值