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

求助:如何在Angular中实现带嵌套结构的表格?

Angular 嵌套结构表格实现方案

单层子项场景实现

如果只是单层父项嵌套子项的结构,直接通过rowspan结合*ngFor就能实现,无需复杂逻辑。

1. 定义数据结构

在组件类中定义包含子项的表格数据结构:

interface TableItem {
  id: number;
  name: string;
  category: string;
  children?: TableItem[];
}

// 模拟表格数据
tableData: TableItem[] = [
  {
    id: 1,
    name: '父项1',
    category: '分类A',
    children: [
      { id: 11, name: '子项1-1', category: '分类A' },
      { id: 12, name: '子项1-2', category: '分类A' }
    ]
  },
  {
    id: 2,
    name: '父项2',
    category: '分类B',
    children: [
      { id: 21, name: '子项2-1', category: '分类B' }
    ]
  },
  {
    id: 3,
    name: '父项3',
    category: '分类C',
    children: []
  }
];

2. 模板实现

通过ng-container循环父项,父行单元格使用rowspan跨占自身+子项的行数,子行单独渲染剩余列:

<table border="1" cellpadding="8" cellspacing="0">
  <thead>
    <tr>
      <th>ID</th>
      <th>名称</th>
      <th>分类</th>
      <th>操作</th>
    </tr>
  </thead>
  <tbody>
    <ng-container *ngFor="let item of tableData">
      <!-- 父行 -->
      <tr>
        <td [rowspan]="item.children?.length ? item.children.length + 1 : 1">{{ item.id }}</td>
        <td [rowspan]="item.children?.length ? item.children.length + 1 : 1">{{ item.name }}</td>
        <td [rowspan]="item.children?.length ? item.children.length + 1 : 1">{{ item.category }}</td>
        <td>父项操作</td>
      </tr>
      <!-- 子行 -->
      <tr *ngFor="let child of item.children">
        <td>{{ child.id }}</td>
        <td>{{ child.name }}</td>
        <td>{{ child.category }}</td>
        <td>子项操作</td>
      </tr>
    </ng-container>
  </tbody>
</table>

多层嵌套场景实现

如果需要支持无限层级的嵌套结构,使用递归组件是最简洁的方案。

1. 创建递归行组件

新建table-row.component.ts,组件自身调用自身来处理多层子项:

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

interface TableItem {
  id: number;
  name: string;
  category: string;
  children?: TableItem[];
}

@Component({
  selector: 'app-table-row',
  template: `
    <tr>
      <td [rowspan]="getTotalRowspan(item)">{{ item.id }}</td>
      <td [rowspan]="getTotalRowspan(item)">{{ item.name }}</td>
      <td [rowspan]="getTotalRowspan(item)">{{ item.category }}</td>
      <td>{{ item.children?.length ? '父项操作' : '普通项操作' }}</td>
    </tr>
    <!-- 递归渲染子项 -->
    <ng-container *ngFor="let child of item.children">
      <app-table-row [item]="child"></app-table-row>
    </ng-container>
  `
})
export class TableRowComponent {
  @Input() item!: TableItem;

  // 递归计算当前项需要跨占的总行数
  getTotalRowspan(item: TableItem): number {
    let total = 1; // 自身占1行
    if (item.children?.length) {
      item.children.forEach(child => {
        total += this.getTotalRowspan(child);
      });
    }
    return total;
  }
}

2. 父组件模板使用递归组件

在父组件的模板中引入递归组件,循环渲染顶层数据:

<table border="1" cellpadding="8" cellspacing="0">
  <thead>
    <tr>
      <th>ID</th>
      <th>名称</th>
      <th>分类</th>
      <th>操作</th>
    </tr>
  </thead>
  <tbody>
    <app-table-row *ngFor="let item of tableData" [item]="item"></app-table-row>
  </tbody>
</table>

注意事项

  • 确保rowspan计算准确:单层场景直接取子项数量+1,多层场景必须递归统计所有子项的总行数
  • 样式可自定义:可以通过CSS替代border、cellpadding属性,实现更美观的表格样式
  • 折叠/扩展功能:若需要点击父项显示/隐藏子项,可在组件中添加isExpanded状态,通过*ngIf控制子项的渲染

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:40:26