[求助] elementui 中 form 与 table 组件一起使用,排序后插入数据索引不对。

2019-12-06 16:07:46 +08:00
 waiaan
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Demo</title>
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <style>

  </style>
</head>

<body>
  <div id="app">
    <div class="table-container">
      <el-form ref="form" :model="jobsData" label-width="0" :rules="formRules" :inline="true">
        <el-table :data="jobsData.rows" header-cell-class-name="header-cell"
          :default-sort="{prop: 'job_title', order: 'ascending'}" stripe>
          <el-table-column label="index" width="100" align="center">
            <template slot-scope="scope">
              <span>
                {{scope.$index+1}}
              </span>
            </template>
          </el-table-column>
          <el-table-column prop="job_id" label="job id" sortable>
            <template slot-scope="scope">
              <div v-if="scope.row.status==='show'">
                {{scope.row.job_id}}
              </div>
              <div v-else>
                <el-form-item :prop="'rows.'+scope.$index+'.job_id'" :rules="formRules.job_id">
                  <el-input v-model="scope.row.job_id"></el-input>
                </el-form-item>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="job_title" label="job title" sortable>
            <template slot-scope="scope">
              <div v-if="scope.row.status==='show'">
                {{scope.row.job_title}}
              </div>
              <div v-else>
                <el-form-item :prop="'rows.'+scope.$index+'.job_title'" :rules="formRules.job_title">
                  <el-input v-model="scope.row.job_title"></el-input>
                </el-form-item>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="min_salary" label="min salary" align="center" sortable>
            <template slot-scope="scope">
              <div v-if="scope.row.status==='show'">
                {{scope.row.min_salary}}
              </div>
              <div v-else>
                <el-form-item :prop="'rows.'+scope.$index+'.min_salary'">
                  <el-input-number v-model="scope.row.min_salary" :min="0"></el-input-number>
                </el-form-item>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="max_salary" label="max salary" align="center" sortable>
            <template slot-scope="scope">
              <div v-if="scope.row.status==='show'">
                {{scope.row.max_salary}}
              </div>
              <div v-else>
                <el-form-item :prop="'rows.'+scope.$index+'.max_salary'">
                  <el-input-number v-model.trim="scope.row.max_salary" :min="0"></el-input-number>
                </el-form-item>
              </div>
            </template>
          </el-table-column>
          <el-table-column align="center">
            <template slot="header">
              <el-button type="primary" size="small" @click="handleAdd">
                + Add
              </el-button>
            </template>
            <template slot-scope="scope">
              <div v-if="scope.row.status==='show'">
                <el-button size="mini" @click.stop="handleEdit(scope)">Edit</el-button>
                <el-button size="mini" type="danger" @click.stop="handleDelete(scope.$index, scope.row)">Delete
                </el-button>
              </div>
              <div v-else-if="scope.row.status==='edit'">
                <el-button type="primary" size="mini" @click.stop="save(scope,'modify')">Save</el-button>
                <el-button size="mini" type="danger" @click.stop="cancleSave(scope)">Cancle</el-button>
              </div>
              <div v-else-if="scope.row.status==='add'">
                <el-button type="primary" size="mini" @click.stop="save(scope,'add')">Add</el-button>
                <el-button size="mini" type="danger" @click.stop="jobsData.rows.pop()">Cancle</el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </el-form>
    </div>
    <el-button type="primary" size="small" @click="handleAdd">
      + Add
    </el-button>
  </div>
  <!-- import Vue before Element -->
  <script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
  <!-- import JavaScript -->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script>
    new Vue({
      el: '#app',
      data() {
        const validateJobId = (rule, value, cb) => {
          const currIndex = ~~rule.fullField.split('.')[1];
          value = value.trim();
          if (value === '') {
            cb(new Error('job_id is required'));
          } else {
            for (let i = 0; i < this.jobsData.rows.length; i++) {
              const { job_id } = this.jobsData.rows[i];
              if (value === job_id && i !== currIndex) {
                cb(new Error('job_id is already exist'))
              }
            }
            cb();
          }
        }
        const validateJobTitle = (rule, value, cb) => {
          const currIndex = ~~rule.fullField.split('.')[1];
          value = value.trim();
          if (value === '') {
            cb(new Error('job_title is required'));
          } else {
            for (let i = 0; i < this.jobsData.rows.length; i++) {
              const { job_title } = this.jobsData.rows[i];
              if (value === job_title && i !== currIndex) {
                cb(new Error('job_title is already exist'))
              }
            }
            cb();
          }
        }
        return {
          jobsData: { rows: [] },
          formRules: {
            job_id: [
              {
                validator: validateJobId
              }
            ],
            job_title: [
              {
                validator: validateJobTitle
              }
            ]
          },
          currEditData: {}
        }
      },
      created() {
        this.fetchData()
      },
      computed: {
      },
      methods: {
        fetchData() {
          this.jobsData = {
            rows: [
              {
                job_id: "FI_ACCOUNT",
                job_title: "Accountant",
                max_salary: 9000,
                min_salary: 4200
              },
              {
                job_id: "AD_ASST",
                job_title: "Administration Assistant",
                max_salary: 6000,
                min_salary: 3000,
              }
            ]
          };
          for (let i = 0; i < this.jobsData.rows.length; i++) {
            this.$set(this.jobsData.rows[i], 'status', 'show');
          }
        },
        resetJobStatus() {
          for (let i = 0; i < this.jobsData.rows.length; i++) {
            this.jobsData.rows[i].status = 'show';
          }
        },
        handleEdit(scope) {
          this.resetJobStatus();
          const { $index } = scope;
          this.currEditData = JSON.parse(JSON.stringify(this.jobsData.rows[$index]));
          this.jobsData.rows[$index].status = 'edit';
        },
        save(scope, type) {
          this.$refs['form'].validate((valid) => {
            if (valid) {
              let { $index } = scope;
              if (type === 'add') {
                $index = this.jobsData.rows.length - 1;
              }
              let job = this.jobsData.rows[$index];
              const { job_id, job_title, max_salary, min_salary } = job;
              if (type === 'modify') {

              } else if (type === 'add') {

              }
            }
          });
        },
        cancleSave(scope) {
          const { $index } = scope;
          this.jobsData.rows.splice($index, 1, JSON.parse(JSON.stringify(this.currEditData)));
          this.jobsData.rows[$index].status = 'show';
        },
        handleAdd() {
          this.resetJobStatus();
          this.jobsData.rows.push({ job_id: '', job_title: '', min_salary: 0, max_salary: 0, status: 'add' });
        }
      }
    })
  </script>
</body>

</html>

表格进行了排序,点击“add”,插入数据,再点击任意“edit”,可编辑的行显示错误。

2999 次点击
所在节点    Vue.js
7 条回复
rain0002009
2019-12-06 16:55:56 +08:00
实验证明 el-table 的默认排序并不改变原数组的顺序,所以你用排序后的 index 来改变原数组的值,哦,你这愚蠢的土拨鼠是要我踢你的屁股吗[doge]
waiaan
2019-12-06 17:11:51 +08:00
@rain0002009
这翻译得好,我知道是这个原因,但是想不到解决的办法。
waiaan
2019-12-06 17:27:13 +08:00
实在不行就只能后端去排了。
bylh
2019-12-06 17:29:37 +08:00
<el-table-column :key="xxx">给每一个 column 绑定唯一 key 值试一试
bylh
2019-12-06 17:34:42 +08:00
@bylh 貌似看错了,忽略此条回复
rain0002009
2019-12-06 18:39:40 +08:00
亲测,直接用传进来的 scope 就能修改了,写这么复杂,what are you 弄啥咧
waiaan
2019-12-06 22:30:47 +08:00
@rain0002009
啥?能否贴一下代码?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/626565

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX