ag-grid-vue纵向合并单元格

一、安装ag-grid-vue并引入样式

ag-grid中文文档
ag-grid英文文档

1. 安装ag-grid包

npm install ag-grid-community ag-grid-vue --save-dev

2. 引入样式文件(App.vue),这里以ag-theme-alpine主题为例

  @import '../node_modules/ag-grid-community/styles/ag-grid.css';
  @import '../node_modules/ag-grid-community/styles/ag-theme-alpine.css';
  @import "style/ag-grid.scss";

二、使用案例

1. 基本使用

(1) 引入AgGridVue

import {
        AgGridVue
    } from "ag-grid-vue3";

(2) html部分

<ag-grid-vue class="ag-theme-alpine ag-wrap" :columnDefs="orderDefs" :rowData="orderData"
                @gridReady="onGridReady">
</ag-grid-vue>

(3) js部分

data

    const orderDefs = [{
            headerName: '订单编号',
            field: 'orderCode',
            width: 200,
        }, {
            headerName: '类型',
            field: 'sendType',
        }, {
            headerName: '日期',
            field: 'sendDate',
        }, {
            headerName: '状态',
            field: 'orderStatus',
        }
    ]
    const orderData = [
           {
                id: 1,
                orderCode: "YHHB2022082001001",
                sendType: "正常检测",
                sendDate: "2022-08-20",
                orderStatus: "待发送",
            },
            {
                id: 2,
                orderCode: "YHHB2022082001002",
                sendType: "申请复检",
                sendDate: "2022-08-20",
                orderStatus: "待发送",
            },
            {
                id: 3,
                orderCode: "YHHB2022082001003",
                sendType: "正常检测",
                sendDate: "2022-08-20",
                orderStatus: "待发送",
            }
    ]

(4) css部分

   .app-container {
        height: 100%;
        padding: 12px;
    }

    .form-wrap {
        height: 50%;
        display: flex;
        flex-direction: column;
        border: 1px solid #babfc7;
        padding: 6px;
        margin-bottom: 10px;
    }

    .ag-wrap {
        flex: 1;
    }
    
   :deep(.ag-ltr .ag-cell) {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0;
        text-align: center;
    }
    
    :deep(.ag-header-cell-label) {
        justify-content: center;
    }     

(5) 展示效果

在这里插入图片描述

2. 根据数值动态控制显示内容或者改变样式

(1) 配置orderDefs里面某个字段的cellRenderer配置项

{
            headerName: '检测结果',
            field: 'projectCheckValue',
            cellRenderer: (params) => {
                if (params.value === '合格') {
                    return `<div style="background:#CAF982;width:100%" }}> ${params.value}</div>`;
                } else if (params.value === '不合格') {
                    return `<div style="background:#EC808D;width:100%" }}> ${params.value}</div>`;
                } else {
                    return `<div style="background:#D7D7D7;width:100%" }}> ${params.value}</div>`;
                }
            }
        }

(2) 展示效果

在这里插入图片描述

3. 动态控制行的样式

这里以判断订单状态来改变行的背景色为例

(1) 配置grid-options

html

<ag-grid-vue class="ag-theme-alpine ag-wrap" :columnDefs="orderDefs" :rowData="orderData"
                :grid-options="gridOptions" @gridReady="onGridReady">
</ag-grid-vue>
data
 const gridOptions = {
        rowHeight: 40,
        headerHeight: 40, // 设置表格表头的行高
        getRowStyle: (params) => {
            return ChangRowColor(params)
        }
    };
methods
// 渲染行的颜色
    const ChangRowColor = (params) => {
        if (params.data.orderStatus=== '待发送') {
            return {
                'background-color': '#81D3F8'
            }
        }
    };
  // 表格创建完成后执行
  const onGridReady = (params) => {
    // 获取gridApi
    gridApi.value = params.api;
    columnApi.value = params.columnApi;
    // 调整表格列宽大小自适应
    gridApi.value.sizeColumnsToFit();
  }

(2) 展示效果

在这里插入图片描述

4. 纵向合并单元格+选择框

效果如图:
在这里插入图片描述

(1) 开启suppressRowTransform等属性,注意拼写!!本人踩了个大坑

<ag-grid-vue class="ag-theme-alpine ag-wrap" :columnDefs="columnDefs" :rowData="rowData"
      :suppressRowTransform="true" :rowSelection="rowSelection" @gridReady="onGridReady"
      @selection-changed="onSelectionChanged">
</ag-grid-vue>

(2) data数据+方法+css

data
const rowSelection = 'multiple'; // 设置多选
配置columnDefs
const columnDefs = [
{
      headerName: '',
      // checkboxSelection: true,
      headerCheckboxSelection: true,
      width: 100,
      cellClassRules: {
        'span-item': "value !== ''"
      },
      rowSpan: (params) => {
        return rowSpanItem(params)
      },
      checkboxSelection: (params) => {
        return params.data ?
          params.node.childIndex % 5 === 0 :
          false;
      },
      checkboxSelection: true,//禁止拖动
    },
    {
      headerName: '序号',
      maxWidth: 120,
      rowSpan: (params) => {
        return rowSpanItem(params)
      },
      cellClassRules: {
        'span-item': "value !== ''"
      },
      cellRenderer: (params) => {
        if (params.node && params.node.childIndex % 5 === 0) {
          return `<div style="height:100%;" }}> ${params.node.childIndex/5+1}</div>`;
        }
      }
    }, {
      headerName: '样品编码',
      field: 'sampleCode',
      width: 200,
      rowSpan: (params) => {
        return 5;
      },
      cellClassRules: {
        'span-item': function (params) {
          if (params.data.id !== '') {
            return true
          } else {
            return false;
          }
        }
      },
      cellRenderer: (params) => {
        if (params.data.id !== '') {
          return `<div }}> ${params.value}</div>`; // 用于字体垂直居中   
        }
      }
    },
]
methods
  // 复选框发生改变时 判断全选框是否勾选
  const onSelectionChanged = (val) => {
    var selRows = gridApi.value.getSelectedRows();
    let arr = rowData.value.filter(item => {
      return item.sampleCode !== ""
    })
    if (arr.length === selRows.length) {
      gridApi.value.selectAll();
    }
  };
    // 合并方法
  const rowSpanItem = (param) => {
    if (param.node && param.node.childIndex % 5 === 0) {
        // console.log(param.node.childIndex)
        return 5
      } else {
        return 1
    }
  };
css样式
  :deep(.span-item) {
    background-color: #fff;
    border-right: 1px solid lightgrey;
    border-bottom: 1px solid lightgrey;
  }
  :deep(.ag-cell-value) {
    border-right: 1px solid lightgrey;
  }

  :deep(.ag-cell-wrapper .ag-cell-value) {
    border: 0;
  }

  :deep(.ag-cell-value span) {
    width: 100%;
  }

  :deep(.ag-center-cols-container) {
    overflow: hidden;
  }

  :deep(.ag-ltr .ag-cell-focus:not(.ag-cell-range-selected):focus-within) {
    border-color: transparent;
    border-right: 1px solid lightgrey;
    border-bottom: 1px solid lightgrey;
  }

(3) 重点!!数据格式

以这里5行一组为例,只有每组的第一条需要id,其他的id置为空即可
在这里插入图片描述

5. 纵向合并后添加分页

(1)使用ant-design自定义分页

    <a-pagination v-model:current="current" v-model:pageSize="pageSize" :total="total" show-size-changer :show-total="total => `共 ${total} 条`" 
    @showSizeChange="onShowSizeChange" />

(2)获取列表后计算total值

total.value = rowData.value.length / 5

(3)methods方法

  // 分页发生改变
  const onShowSizeChange = (page: number, size: number) => {
    pageSize.value = size * 5;
    current.value = page;
    // 调用接口
  }

6. 补充一种动态合并纵向单元格方法

rowSpan配置

判断多个属性

// 合并方法
  const rowSpanItem = (param) => {
    // 定义需要合并的属性名
    const arr = ["sampleCode", "sampleType"];
    // console.log(param.data)
    if (arr.indexOf(param.column.colId) !== -1) {
      const data = arr.slice(0, arr.indexOf(param.column.colId) + 1);
      // 每个值第一次出现时对应的索引
      const first = rowData.value.findIndex(item => data.every((v) => item[v] === param.data[v]));
      // console.log(first)
      if (param.node.childIndex === first) {
        // 计算与索引值相同值出现的次数
        const rowspan = rowData.value.filter(item => {
          return data.every(v => item[v] === param.data[v]);
        }).length;
        return rowspan;//返回合并行
      } else {
        return 1;
      }
    } 
  }

判断单个属性

const first = rowData.value.findIndex(item => item['sample_code'] === params.data['sample_code']);
                if (params.node.childIndex === first) {
                    const rowspan = rowData.value.filter(item => {
                        return item['sample_code']===params.data['sample_code']
                    }).length;
                    return `<div style="height:100%;" }}> ${params.node.childIndex/rowspan+1}</div>`;
                }

7. 配置默认项

<ag-grid-vue
        class="ag-theme-alpine ag-wrap"
        :columnDefs="orderDefs"
        overlayNoRowsTemplate="暂无数据"
        :rowData="orderData"
        :defaultColDef="defaultColDef"
        :headerHeight="28"
        :rowHeight="28"
        rowSelection="multiple"
        :grid-options="gridOptions"
        @gridReady="onGridReady"
        @rowClicked="onRowClicked"
      >
      </ag-grid-vue>
const defaultColDef = {
  width: 170,
  resizable: true,
  cellStyle: { "border-right-color": "#e8eaed" },
};

8. 单元格内操作栏添加点击事件(2个以上)

配置columnDefs

{
    headerName: "操作",
    field: "action",
    width: 400,
    rowSpan: (params) => {
      return rowSpanItem(params);
    },
    cellClassRules: {
      "span-item": "value !== ''",
    },
    cellRenderer: (params) => {
      var btn1 = document.createElement("span");
      console.log(params);
      btn1.innerHTML = "检测结果归档";
      btn1.style = "margin-right:6px;color:#4C78FC";
      btn1.addEventListener("click", () => {
        setTimeout(() => {
          let arr = [];
          arr[0] = active.value;
          const req = {
            sample_ids: arr,
          };
          const res = approveResult(req);
          if (res.code === "000000") {
          }
        }, 500);
      });
      var btn2 = document.createElement("span");
      btn2.innerHTML = "重新录入数据";
      btn2.style = "color:#4C78FC";
      btn2.addEventListener("click", () => {
        setTimeout(() => {
          let arr = [];
          arr[0] = active.value;
          const req = {
            sample_ids: arr,
          };
          const res = reRecord(req);
          if (res.code === "000000") {
          }
        }, 500);
      });
      const cell = document.createElement("div");
      cell.style = "display:flex;";
      cell.appendChild(btn1);
      cell.appendChild(btn2);
      return cell;
    },
    lockPosition: true,
  },
const rowSpanItem = (params) => {
  const first = rowData.value.findIndex(
    (item) => item["sample_code"] === params.data["sample_code"]
  );
  if (params.node.childIndex === first) {
    const rowspan = rowData.value.filter((item) => {
      return item["sample_code"] === params.data["sample_code"];
    }).length;
    return rowspan;
  } else {
    return 1;
  }
};

9. 开启suppressRowClickSelection属性

合并单元格中编辑子数据时会触发行事件,导致gridApi.value.getSelectedRows方法中出现值,开始suppressRowClickSelection属性后就可以避免这一现象发生

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Vue Element Table 纵向表格是一种表格布局方式,其中表头和表体的列是垂直排列的,而行则是水平排列的。这种表格布局方式适用于需要展示大量数据的情况,可以让用户更方便地查看和比较数据。Vue Element Table 纵向表格还支持排序、筛选、分页等功能,可以满足不同的数据展示需求。 ### 回答2: Vue Element Table是一个基于Vue.js的高效表格组件,它提供了丰富的表格需求实现方式,包括纵向表格。所谓纵向表格就是需要在表格中展示多列数据,同时列名跨行展示,一般用于展示多条件的数据对比,如财务报表等。 在Vue Element Table中实现纵向表格,需要先定义好表头,即列名。表头可以使用el-table-column组件来实现,该组件具有属性label和prop,分别代表列名和数据对应的字段名。使用纵向表格时,需要同时设置rowspan属性,用于定义列名所占据的行数。 下一步是定义表格数据。表格数据是一个数组,数组中每个元素代表一行数据,其中每个元素的属性名需与列名中的prop属性一致,用于映射数据到表格中。在纵向表格中,由于一行数据可能会对应多个字段,因此需要用对象或数组来表示某一行的多列数据。 完成表头和表格数据的定义后,需要将它们传给Vue Element Table组件,并在template中使用el-table和el-table-column组件构建表格结构。在el-table-column组件中,需要根据表头定义,使用自定义的template来显示数据,同时为表头设置rowspan属性。 代码示例: <template> <el-table :data="tableData" style="width: 100%"> <el-table-column label="字段1" prop="field1" rowspan="3"> <template slot-scope="scope">{{ scope.row.field1 }}</template> </el-table-column> <el-table-column label="字段2" prop="field2" rowspan="3"> <template slot-scope="scope">{{ scope.row.field2 }}</template> </el-table-column> <el-table-column label="字段3" prop="field3" rowspan="2"> <template slot-scope="scope">{{ scope.row.field3 }}</template> </el-table-column> <el-table-column label="字段4" prop="field4" rowspan="2"> <template slot-scope="scope">{{ scope.row.field4 }}</template> </el-table-column> <el-table-column label="字段5" prop="field5" rowspan="2"> <template slot-scope="scope">{{ scope.row.field5 }}</template> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { field1: '数据1', field2: '数据2', field3: ['数据3', '数据4'], field4: ['数据5', '数据6'], field5: ['数据7', '数据8'] }, { field1: '数据9', field2: '数据10', field3: ['数据11', '数据12'], field4: ['数据13', '数据14'], field5: ['数据15', '数据16'] } ] } } } </script> 以上示例中,表格中有5个字段需要展示,其中字段1和2跨3行,字段3-5跨2行,数据由一个数组来表示。当Vue Element Table渲染该表格时,会自动将数据显示在对应的单元格中,同时根据rowspan属性设置表头跨行展示。整个表格结构具有美观的外观和高效的性能。 ### 回答3: Vue Element Table是一种非常常见的数据表格展示组件,它支持水平和竖向布局。在Vue Element Table中,纵向表格是一种非常常见的表格布局方式。这种布局方式的特点是将列当作行来展示,即将表中的每一列转换为一行,原先的每一行则成为一个单元格。 纵向表格可以用来展示具有多种属性的数据,让用户能够更加轻松地比较不同属性之间的差异。例如,如果我们要展示一个商品列表,我们可以将商品名称、价格、销量等属性分别展示在每一个单元格中。 在使用Vue Element Table时,我们可以使用该组件提供的prop来控制表格的列数、行数和表头样式等参数。对于纵向表格,我们需要通过配置组件的columns参数来指定每一列的数据字段和样式。Vue Element Table还提供了一系列的插槽用于自定义表格的样式和内容。 总的来说,Vue Element Table的纵向表格是一种非常常见和实用的表格布局方式,它可以用于展示具备多属性的数据,并能够方便地进行比较和查看。如需更多详细信息,可参照Vue Element Table官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

trabecula_hj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值