Ant vue table table data dynamic merge

antd table dynamic row merge

merge effect

insert image description here

step method

1. Dynamically calculate the number of rows to be merged each time under the computed node

  computed: {
    
    
    columns() {
    
    
      return [
        {
    
    
          title: "区域",
          dataIndex: "area",
          customRender: (text, row, index) => {
    
    
            const obj = {
    
    
              children: text !== null ? text : "",
              attrs: {
    
    
                rowSpan: 1,
              },
            };
            obj.attrs.rowSpan = this.renderCells(text, this.currentTable, "area",index);
            return obj;
          },
        },
        {
    
    
          title: "名称",
          dataIndex: "name",
        },
        {
    
    
          title: "数量",
          dataIndex: "count",
        },
        {
    
    
          title: "进度",
          dataIndex: "progress",
        },
      ];
    },
  }

2. Define the method of merging cells under the methods node

renderCells(text, data, key, index) {
    
    
      if (data.length < 1) {
    
    
        return 1;
      }
      if (text === "" || text === null) {
    
    
        data[index].rowNum = 1;
        return 1;
      }
      // 上一行该列数据是否一样
      if (index !== 0 && text === data[index - 1][key] && index % this.pagination.pageSize != 0) {
    
    
        data[index].rowNum = 0;
        return 0;
      }
      let rowSpan = 1;
      // 判断下一行是否相等
      for (let i = index + 1; i < data.length; i++) {
    
    
        if (text !== data[i][key]) {
    
    
          break;
        }
        rowSpan++;
      }
      data[index].rowNum = rowSpan;
      return rowSpan;
    }

3. If you want to get all the data at one time for pagination, you need to modify it when calculating columns

    columns() {
    
    
      return [
        {
    
    
          title: "区域",
          dataIndex: "area",
          customRender: (text, row, index) => {
    
    
            const obj = {
    
    
              children: text !== null ? text : "",
              attrs: {
    
    
                rowSpan: 1,
              },
            };
            obj.attrs.rowSpan = this.renderCells(text, this.currentTable, "area", Number(index)+Number(this.pagination.pageSize * (this.pagination.current - 1)));
            return obj;
          },
        },
        {
    
    
          title: "名称",
          dataIndex: "name",
        },
        {
    
    
          title: "数量",
          dataIndex: "count",
        },
        {
    
    
          title: "进度",
          dataIndex: "progress",
        },
      ];
    },

Reference article: ant design vue dynamic form merge

merge effect

If we want to merge with the same name column, we need to modify the original code. The premise of merging is that the regions are the same and the names are the same. We only need to add a layer of judgment when calculating the number of merged rows.
insert image description here

    renderCells(text, data, key, index) {
    
    
      if (data.length < 1) {
    
    
        return 1;
      }
      if (text === "" || text === null) {
    
    
        data[index].rowNum = 1;
        return 1;
      }
      // 上一行该列数据是否一样
      if (index !== 0 && text === data[index - 1][key] && index % this.pagination.pageSize != 0) {
    
    
        if(key === 'name'){
    
    
          if(data[index-1]['area'] === data[index]['area']){
    
    
            data[index].rowNum = 0
            return 0;
          }
        }else{
    
    
          data[index].rowNum = 0;
          return 0;
        }

      }
      let rowSpan = 1;
      // 判断下一行是否相等
      for (let i = index + 1; i < data.length; i++) {
    
    
        if(key === 'name' && data[i]['area'] !== data[index]['area']){
    
    
          break;
        }
        if (text !== data[i][key] ) {
    
    
          break;
        }
        rowSpan++;
      }
      data[index].rowNum = rowSpan;
      return rowSpan;
    },

cell editable

non-merged lines

You can refer to the official ant-design-vue editable cell, the official example is as follows:

<template>
  <div>
    <a-button class="editable-add-btn" @click="handleAdd">
      Add
    </a-button>
    <a-table bordered :data-source="dataSource" :columns="columns">
      <template slot="name" slot-scope="text, record">
        <editable-cell :text="text" @change="onCellChange(record.key, 'name', $event)" />
      </template>
      <template slot="operation" slot-scope="text, record">
        <a-popconfirm
          v-if="dataSource.length"
          title="Sure to delete?"
          @confirm="() => onDelete(record.key)"
        >
          <a href="javascript:;">Delete</a>
        </a-popconfirm>
      </template>
    </a-table>
  </div>
</template>
<script>
const EditableCell = {
    
    
  template: `
      <div class="editable-cell">
        <div v-if="editable" class="editable-cell-input-wrapper">
          <a-input :value="value" @change="handleChange" @pressEnter="check" /><a-icon
            type="check"
            class="editable-cell-icon-check"
            @click="check"
          />
        </div>
        <div v-else class="editable-cell-text-wrapper">
          {
     
     { value || ' ' }}
          <a-icon type="edit" class="editable-cell-icon" @click="edit" />
        </div>
      </div>
    `,
  props: {
    
    
    text: String,
  },
  data() {
    
    
    return {
    
    
      value: this.text,
      editable: false,
    };
  },
  methods: {
    
    
    handleChange(e) {
    
    
      const value = e.target.value;
      this.value = value;
    },
    check() {
    
    
      this.editable = false;
      this.$emit('change', this.value);
    },
    edit() {
    
    
      this.editable = true;
    },
  },
};
export default {
    
    
  components: {
    
    
    EditableCell,
  },
  data() {
    
    
    return {
    
    
      dataSource: [
        {
    
    
          key: '0',
          name: 'Edward King 0',
          age: '32',
          address: 'London, Park Lane no. 0',
        },
        {
    
    
          key: '1',
          name: 'Edward King 1',
          age: '32',
          address: 'London, Park Lane no. 1',
        },
      ],
      count: 2,
      columns: [
        {
    
    
          title: 'name',
          dataIndex: 'name',
          width: '30%',
          scopedSlots: {
    
     customRender: 'name' },
        },
        {
    
    
          title: 'age',
          dataIndex: 'age',
        },
        {
    
    
          title: 'address',
          dataIndex: 'address',
        },
        {
    
    
          title: 'operation',
          dataIndex: 'operation',
          scopedSlots: {
    
     customRender: 'operation' },
        },
      ],
    };
  },
  methods: {
    
    
    onCellChange(key, dataIndex, value) {
    
    
      const dataSource = [...this.dataSource];
      const target = dataSource.find(item => item.key === key);
      if (target) {
    
    
        target[dataIndex] = value;
        this.dataSource = dataSource;
      }
    },
    onDelete(key) {
    
    
      const dataSource = [...this.dataSource];
      this.dataSource = dataSource.filter(item => item.key !== key);
    },
    handleAdd() {
    
    
      const {
    
     count, dataSource } = this;
      const newData = {
    
    
        key: count,
        name: `Edward King ${
      
      count}`,
        age: 32,
        address: `London, Park Lane no. ${
      
      count}`,
      };
      this.dataSource = [...dataSource, newData];
      this.count = count + 1;
    },
  },
};
</script>

insert image description here

Dynamically merge editable cells

In the actual application process, you may encounter the need to dynamically merge editable cells. It is known that scopedSlots can help us edit cells, and customRender can customize dynamic merged cells. But after practice, it is found that the two cannot be used at the same time. Referring to the solution of dynamically merging editable cells in the ant-design-vue table, it is found that the conflict between scopedSlots and customRender can be solved through JSX syntax

  computed: {
    
    
    columns() {
    
    
      return [
        {
    
    
          title: "区域",
          dataIndex: "area",
          scopedSlots: {
    
     customRender: 'area' },
          customRender: (text, row, index) => {
    
    
            const obj = {
    
    
              children: <editable-cell text={
    
    text} onChange={
    
    (val) => this.onCellChange(row.id,'area',val)}></editable-cell>,
              attrs: {
    
    
                rowSpan: 1,
              },
            };
            obj.attrs.rowSpan = this.mergeCells(text, this.currentTable, "area", Number(index)+Number(this.pagination.pageSize * (this.pagination.current - 1)));
            return obj;
          },
        },
        {
    
    
          title: "名称",
          dataIndex: "name",
         
        },
        {
    
    
          title: "数量",
          dataIndex: "count",
        },
        {
    
    
          title: "进度",
          dataIndex: "progress",
        },
      ];
    },
  },

achieve effect

insert image description here

Guess you like

Origin blog.csdn.net/qq_46258819/article/details/127298168