V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waiaan
V2EX  ›  Vue.js

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

  •  
  •   waiaan · 2019-12-06 16:07:46 +08:00 · 3090 次点击
    这是一个创建于 1816 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <!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/[email protected]/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”,可编辑的行显示错误。

    7 条回复    2019-12-06 22:30:47 +08:00
    rain0002009
        1
    rain0002009  
       2019-12-06 16:55:56 +08:00
    实验证明 el-table 的默认排序并不改变原数组的顺序,所以你用排序后的 index 来改变原数组的值,哦,你这愚蠢的土拨鼠是要我踢你的屁股吗[doge]
    waiaan
        2
    waiaan  
    OP
       2019-12-06 17:11:51 +08:00
    @rain0002009
    这翻译得好,我知道是这个原因,但是想不到解决的办法。
    waiaan
        3
    waiaan  
    OP
       2019-12-06 17:27:13 +08:00
    实在不行就只能后端去排了。
    bylh
        4
    bylh  
       2019-12-06 17:29:37 +08:00
    <el-table-column :key="xxx">给每一个 column 绑定唯一 key 值试一试
    bylh
        5
    bylh  
       2019-12-06 17:34:42 +08:00
    @bylh 貌似看错了,忽略此条回复
    rain0002009
        6
    rain0002009  
       2019-12-06 18:39:40 +08:00
    亲测,直接用传进来的 scope 就能修改了,写这么复杂,what are you 弄啥咧
    waiaan
        7
    waiaan  
    OP
       2019-12-06 22:30:47 +08:00
    @rain0002009
    啥?能否贴一下代码?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1022 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 20:13 · PVG 04:13 · LAX 12:13 · JFK 15:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.