You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular Material表格中实现基于条件的rowspan单元格合并

在Angular Material表格中实现条件化单元格合并(除指定列外)

要实现当IPSCaseCode与下一行匹配时,除Amount列外合并对应行的需求,核心思路是先预处理数据,计算每个单元格的rowspan值并标记需隐藏的重复行,再在模板中通过绑定属性和条件渲染实现合并效果。

步骤1:预处理数据(组件逻辑)

首先需要对原始数据进行分组和标记,计算每个单元格的rowspan,同时标记重复行用于隐藏。假设你的数据结构如下:

interface RequestData {
  IPSCaseCode: string;
  Date: Date; // 示例其他列
  Amount: number;
  // 其他业务字段
}

在组件中添加处理逻辑:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-request-table',
  templateUrl: './request-table.component.html',
  styleUrls: ['./request-table.component.css']
})
export class RequestTableComponent implements OnInit {
  // 原始请求数据
  requests: RequestData[] = [
    // 你的数据填充在这里
  ];
  // 处理后的数据,包含rowspan和隐藏标记
  processedRequests: (RequestData & { rowspan: Record<string, number>, hide: boolean })[] = [];
  // 表格显示列
  displayedColumns = ['IPSCaseCode', 'Date', 'Amount'];

  ngOnInit(): void {
    this.processRowspanData();
  }

  private processRowspanData(): void {
    if (!this.requests.length) return;

    // 先按IPSCaseCode排序,确保同组数据连续
    const sortedRequests = [...this.requests].sort((a, b) => 
      a.IPSCaseCode.localeCompare(b.IPSCaseCode)
    );

    // 按IPSCaseCode分组,计算每组长度
    const groups = sortedRequests.reduce((acc, item) => {
      const key = item.IPSCaseCode;
      acc[key] = acc[key] || [];
      acc[key].push(item);
      return acc;
    }, {} as Record<string, RequestData[]>);

    // 遍历分组,生成带rowspan和隐藏标记的数据
    Object.values(groups).forEach(group => {
      const groupSize = group.length;
      group.forEach((item, index) => {
        // 构建各列的rowspan:除Amount列外,其他列rowspan为组长度
        const rowspan: Record<string, number> = {};
        Object.keys(item).forEach(col => {
          rowspan[col] = col === 'Amount' ? 1 : groupSize;
        });

        this.processedRequests.push({
          ...item,
          rowspan,
          hide: index !== 0 // 仅保留每组第一行,其余标记为隐藏
        });
      });
    });
  }
}

步骤2:模板中实现合并渲染

在Angular Material表格模板中,通过[attr.rowspan]绑定计算好的rowspan值,并用*ngIf控制重复行的单元格显示:

<table mat-table [dataSource]="processedRequests" class="mat-elevation-z8">

  <!-- IPSCaseCode列:合并相同值的行 -->
  <ng-container matColumnDef="IPSCaseCode">
    <th mat-header-cell *matHeaderCellDef> IPS Case Code </th>
    <td mat-cell *matCellDef="let row" 
        [attr.rowspan]="row.rowspan.IPSCaseCode"
        *ngIf="!row.hide">
      {{row.IPSCaseCode}}
    </td>
  </ng-container>

  <!-- Date列:合并相同IPSCaseCode组内的行 -->
  <ng-container matColumnDef="Date">
    <th mat-header-cell *matHeaderCellDef> 日期 </th>
    <td mat-cell *matCellDef="let row" 
        [attr.rowspan]="row.rowspan.Date"
        *ngIf="!row.hide">
      {{row.Date | date:'yyyy-MM-dd'}}
    </td>
  </ng-container>

  <!-- Amount列:不合并,每行都显示 -->
  <ng-container matColumnDef="Amount">
    <th mat-header-cell *matHeaderCellDef> 金额 </th>
    <td mat-cell *matCellDef="let row"> {{row.Amount}} </td>
  </ng-container>

  <!-- 表头行 -->
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <!-- 数据行:所有行都保留(因为Amount列需要每行显示) -->
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

关键说明

  1. 排序必要性:必须先按IPSCaseCode排序,确保相同值的行连续,否则分组和合并会出错。
  2. 多条件合并扩展:如果需要同时匹配多个字段(比如原Web Forms中的日期),只需修改分组的key,例如:
    const key = `${item.IPSCaseCode}-${item.Date.toISOString().split('T')[0]}`;
    
  3. 行保留逻辑:数据行不能隐藏,因为Amount列需要每行都显示,只隐藏合并列的重复单元格即可。

内容的提问来源于stack exchange,提问作者Akshay Meshram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 06:36:06