Vue + Element ui 實現動態表單,包括新增行/刪除行/動態表單驗證/提交功能

2023-07-10 21:01:05

總結/朱季謙

最近通過Vue + Element ui實現了動態表單功能,該功能還包括了動態表單新增行、刪除行、動態表單驗證、動態表單提交功能,趁熱打鐵,將開發心得記錄下來,方便以後再遇到類似功能時,直接拿來應用。

簡化的頁面效果圖如下:

最開始,我是用了純粹的表格形式,後來發現,這種形式在提交的時候,不好對每個輸入框做校驗,若是表單形式話,就可以直接通過rule設定每個輸入框的驗證,因此,我就在表格裡面巢狀了表單。注意一點是,el-form-item裡的 :prop="scope.$index + '.name'"需要對應el-input的 v-model="studentData[scope.$index].name",兩者都是同一個欄位值。

<template>
  <div >
        <div>
          <div>
            <el-button  size="small"  @click="addRow">新增</el-button>
          </div>
          <!--設定的表單-->
          <el-form :model="studentData" ref="data" label-width="auto">
          <el-table
            border
            :header-cell-style="{ 'text-align': 'center' }"
            :cell-style="{ 'text-align': 'center' }"
            :data="studentData"
            ref="table"
            style="width: 100%"
          >

            <el-table-column align="center"   label="姓名">
              <template slot-scope="scope">
              <!--表格裡面巢狀表單-->
                <el-form-item
                  :prop="scope.$index + '.name'"
                  :rules="{ required: true, message: '姓名不能為空', trigger: 'blur' }"
                >
                <el-input
                  v-model="studentData[scope.$index].name"
                  autocomplete="off"
                  size="small"
                  placeholder="姓名"
                ></el-input>
                </el-form-item>
              </template>
            </el-table-column>

            <el-table-column align="center"  label="年齡">
              <template slot-scope="scope">
                  <el-form-item
                    :prop="scope.$index + '.age'"
                    :rules="{ required: true, message: '年齡不能為空', trigger: 'blur' }"
                  >
                <el-input
                  v-model="studentData[scope.$index].age"
                  autocomplete="off"
                  size="small"
                  type='number'
                  placeholder="收款方開戶行號"
                ></el-input>
                  </el-form-item>
              </template>
            </el-table-column>

            <el-table-column align="center"  label="性別">
              <template slot-scope="scope">
                <el-form-item
                  :prop="scope.$index + '.sex'"
                  :rules="{ required: true, message: '性別不能為空', trigger: 'blur' }"
                >
                <el-input
                  v-model="studentData[scope.$index].sex"
                  autocomplete="off"
                  size="small"
                  placeholder="性別"
                ></el-input>
                </el-form-item>
              </template>
            </el-table-column>

            <el-table-column fixed="right" label="操作" width="100">
              <template slot-scope="scope">
                <el-button
                  @click="handleDeleteRow(studentData[scope.$index])"
                  type="text"
                  size="small"
                >刪除</el-button
                >
              </template>
            </el-table-column>
            
          </el-table>
          </el-form>
        </div>
        
        <div slot="footer" class="dialog-footer" style="margin-bottom: 10px">
          <el-button size="mini"  @click="submit">提交</el-button>
          <el-button size="mini" @click="resetForm()">重置</el-button>
        </div>
  </div>
</template>

定義一個儲存動態表格資料的陣列變數

export default {
  data() {
    return {
      studentData:[],
    };
  },
  ......
}

在methods方法裡增加相關方法,分別是新增行、刪除行、提交——

methods:{

  /**
   * 新增行
   */
  addRow() {
    let index = this.studentData.length ;
    this.studentData.push({
      key: index,
      name:'',
      age:'',
      sex:'',
    });
  },

  /**
   * 刪除行
   * @param row
   */
  handleDeleteRow(row){
    let datas = this.studentData;
    for (var i = 0; i < datas.length; i++){
      if (datas[i].key == row.key){
        datas.splice(i,1);
      }
    }
  },

  /**
   * 提交
   */
  submit() {
    this.$refs["data"].validate(valid => {
      //valid為true,表示表單都已經驗證通過,若為false,說明存在表單驗證失敗
        if (valid) {
          save(this.studentData).then(response => {
            this.$message({
              message: '提交成功',
              type: 'success'
            });
          });
        }
    });
  },

  /**
   * 重置
   */
  resetForm() {
    let datas = this.studentData;
    for (var i = 0; i < datas.length; i++){
      datas[i].name='';
      datas[i].age='';
      datas[i].sex='';
    }
  },
}

設定表單驗證規則,可統一在rules設定,也可以在每一輸入框單獨設定,我這裡是單獨在每一個輸入框裡設定,即:rules="{ required: true, message: '姓名不能為空', trigger: 'blur' }"就可以了,當然,還可以做一些更復雜的自定義規則。

<el-table-column align="center"   label="姓名">
          <template slot-scope="scope">
          <!--表格裡面巢狀表單-->
            <el-form-item
              :prop="scope.$index + '.name'"
              :rules="{ required: true, message: '姓名不能為空', trigger: 'blur' }"
            >
            <el-input
              v-model="studentData[scope.$index].name"
              autocomplete="off"
              size="small"
              placeholder="姓名"
            ></el-input>
            </el-form-item>
          </template>
        </el-table-column>