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

如何在Angular中实现可展开多级网格(无需插件)

实现Angular多级嵌套网格(无插件版)

我明白你的需求啦,不用任何第三方插件,纯Angular自带功能就能搞定这个多级展开的网格。核心思路是给每个数据项维护子项列表和展开状态,再用递归模板来渲染嵌套结构。下面一步步来实现:

第一步:调整数据结构

首先,我们需要给每个数据项添加两个属性:

  • children: []:用来存储当前项的子数据
  • isExpanded: boolean:控制当前项的子网格是否展开

在组件初始化顶层数据的时候,就给每个项加上这两个属性:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-nested-grid',
  templateUrl: './nested-grid.component.html',
  styleUrls: ['./nested-grid.component.css']
})
export class NestedGridComponent {
  values: any[] = [];

  constructor(private http: HttpClient) {
    // 模拟初始加载的顶层数据
    const initialData = [
      {id:1, desc:'test', level: 0},
      {id:2, desc:'testing',level: 0}
    ];
    // 给每个项添加子项数组和展开状态
    this.values = initialData.map(item => ({
      ...item,
      children: [],
      isExpanded: false
    }));
  }

  getTerms(parentId: number, parentItem: any) {
    // 如果已经展开,就切换折叠状态
    if (parentItem.isExpanded) {
      parentItem.isExpanded = false;
      return;
    }
    // 调用接口获取子项数据
    this.http.get(`/get/Term/${parentId}`).subscribe((childData: any[]) => {
      // 给子项也加上children和isExpanded
      const formattedChildren = childData.map(child => ({
        ...child,
        children: [],
        isExpanded: false
      }));
      // 将子项赋值给父项的children数组
      parentItem.children = formattedChildren;
      // 切换展开状态
      parentItem.isExpanded = true;
    });
  }
}

第二步:用递归模板渲染嵌套结构

Angular的ng-template支持递归调用,我们可以用它来渲染任意层级的子网格。模板结构如下:

<table class="nested-table">
  <thead>
    <tr>
      <th>Check</th>
      <th>Result</th>
    </tr>
  </thead>
  <tbody>
    <!-- 递归模板入口:渲染顶层数据 -->
    <ng-container *ngTemplateOutlet="rowTemplate; context: { $implicit: values }"></ng-container>

    <!-- 定义递归渲染的模板 -->
    <ng-template #rowTemplate let-items>
      <tr *ngFor="let item of items">
        <td>
          <label class="checkbox">
            <input type="checkbox">
          </label>
          <!-- 点击ID时调用getTerms,传入父项本身 -->
          <a (click)="getTerms(item.id, item)">{{item.id}}</a>
        </td>
        <td>{{item.desc}}</td>
      </tr>
      <!-- 如果当前项展开且有子项,渲染子表格 -->
      <tr *ngIf="item.isExpanded && item.children.length > 0">
        <td colspan="2">
          <!-- 子表格,用缩进区分层级 -->
          <table class="child-table">
            <tbody>
              <!-- 递归调用模板渲染子项 -->
              <ng-container *ngTemplateOutlet="rowTemplate; context: { $implicit: item.children }"></ng-container>
            </tbody>
          </table>
        </td>
      </tr>
    </ng-template>
  </tbody>
</table>

第三步:添加样式优化显示效果

为了让子网格有明显的层级缩进,我们可以加一点CSS:

.nested-table {
  width: 100%;
  border-collapse: collapse;
}

.nested-table th, .nested-table td {
  border: 1px solid #ddd;
  padding: 8px;
}

.child-table {
  width: 100%;
  border-collapse: collapse;
  margin-left: 20px; /* 子表格缩进 */
}

.child-table td {
  border: none;
  border-bottom: 1px solid #eee;
}

关键逻辑说明

  1. 数据结构扩展:通过给每个项添加children和isExpanded,我们能追踪每个节点的子数据和展开状态,这是实现嵌套的核心。
  2. 递归模板:ng-template的递归调用让我们可以处理任意层级的嵌套,不用手动写多层*ngFor。
  3. 展开/折叠切换:点击ID时,如果已经展开就直接折叠;如果没展开,就请求子数据并展开。

这样就能实现你要的效果:点击顶层ID加载子项并展开子网格,子项ID点击后继续加载下一级,无限嵌套都没问题~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:46:36