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

Angular中用ul/table展示分类与子分类,点击展开子分类的实现咨询

How to Implement Expandable Nested Categories in Angular

Hey Mike, let's get this expandable category display sorted out for your Angular project. We'll break this down into three key steps: transforming your flat data into a nested tree structure, setting up the component logic, and building the expandable UI.

1. Transform Flat Data to Nested Tree Structure

Your raw cats array is flat, so first we need to convert it into a nested tree where each category has a children property containing its subcategories. This makes rendering hierarchical content way easier.

Add this method to your component class:

buildCategoryTree(categories: any[]): any[] {
  const categoryMap = new Map();
  const rootCategories = [];

  // First, create a map of all categories by their ID
  categories.forEach(category => {
    categoryMap.set(category.id, { ...category, children: [] });
  });

  // Then, populate the children for each parent category
  categories.forEach(category => {
    if (category.parent_id === 'root') {
      rootCategories.push(categoryMap.get(category.id));
    } else {
      const parent = categoryMap.get(category.parent_id);
      if (parent) {
        parent.children.push(categoryMap.get(category.id));
      }
    }
  });

  return rootCategories;
}

2. Component Logic Setup

Now, let's set up the variables and initialization logic in your component:

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

@Component({
  selector: 'app-category-tree',
  templateUrl: './category-tree.component.html',
  styleUrls: ['./category-tree.component.css']
})
export class CategoryTreeComponent implements OnInit {
  cats = [
    {"id": "1", "parent_id": 'root', "category": "Dress"},
    {"id": "17", "parent_id": "1", "category": "Dress 2"},
    {"id": "19", "parent_id": "1", "category": "Men"},
    {"id": "30", "parent_id": "19", "category": "Shorts 2"},
    {"id": "31", "parent_id": "19", "category": "Shorts"}
  ];

  categoryTree: any[] = [];
  expandedIds = new Set<string>(); // Tracks which categories are expanded

  ngOnInit(): void {
    this.categoryTree = this.buildCategoryTree(this.cats);
    // Optional: Expand root categories by default so users see them on load
    this.categoryTree.forEach(root => this.expandedIds.add(root.id));
  }

  toggleExpand(categoryId: string): void {
    if (this.expandedIds.has(categoryId)) {
      this.expandedIds.delete(categoryId);
    } else {
      this.expandedIds.add(categoryId);
    }
  }
}

3. Build the Expandable UI with Recursive Template

We'll use Angular's ng-template to create a recursive template that renders each level of categories. This works for any depth of subcategories, so you don't have to worry about hardcoding levels.

In your component's HTML:

<ul class="category-tree">
  <ng-template #categoryList let-categories>
    <li *ngFor="let category of categories">
      <span 
        class="category-item" 
        (click)="toggleExpand(category.id)"
        [class.expanded]="expandedIds.has(category.id)"
      >
        <!-- Show expand/collapse icon based on state -->
        <span *ngIf="category.children.length > 0">
          {{ expandedIds.has(category.id) ? '▼' : '▶' }}
        </span>
        {{ category.category }}
      </span>
      <!-- Render children if category is expanded and has children -->
      <ul *ngIf="expandedIds.has(category.id) && category.children.length > 0">
        <ng-container *ngTemplateOutlet="categoryList; context: { $implicit: category.children }"></ng-container>
      </ul>
    </li>
  </ng-template>

  <!-- Initialize with root categories -->
  <ng-container *ngTemplateOutlet="categoryList; context: { $implicit: categoryTree }"></ng-container>
</ul>

Optional Styling

Add some basic CSS to make the tree look cleaner and more intuitive:

.category-tree {
  list-style: none;
  padding-left: 1rem;
}

.category-item {
  cursor: pointer;
  padding: 0.25rem 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.category-item.expanded {
  font-weight: 500;
}

Alternative: Using ngx-datatables (If You Prefer Tables)

If you want to use ngx-datatables instead of a list, you can leverage the row detail feature:

  1. Define your main table to display parent categories
  2. Use the rowDetail directive to render subcategories when a row is clicked
  3. Filter the subcategories based on the clicked parent's ID

The core logic for tracking expanded rows stays similar to the list approach—you'll just use the table's row click event to toggle expansion and filter subcategories dynamically.

That's it! This implementation will let you click any category to show/hide its subcategories, starting with the root categories visible initially.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:22:32