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

Angular如何检测ng-content内组件数量并合并多列组件?

Merging into a Dynamic Column Row Component

Absolutely! You can combine your app-row-two and app-row-three components into a single dynamic component that automatically detects how many elements/components you've projected into it and wraps each in an x-col div. Here's how to do it:

Step 1: Create the Dynamic Component

First, generate a new component (let's call it app-dynamic-row). Replace its template and class with the following:

Component Template (dynamic-row.component.html)

<div #columnContainer>
  <ng-content></ng-content>
</div>

Component Class (dynamic-row.component.ts)

import { Component, ViewChild, ElementRef, AfterContentInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-dynamic-row',
  templateUrl: './dynamic-row.component.html',
  styleUrls: ['./dynamic-row.component.css']
})
export class DynamicRowComponent implements AfterContentInit, OnDestroy {
  @ViewChild('columnContainer') private columnContainer!: ElementRef<HTMLDivElement>;
  private mutationObserver?: MutationObserver;

  ngAfterContentInit(): void {
    // Initial wrap of projected elements
    this.wrapElementsInColumns();

    // Set up observer to handle dynamic changes (adding/removing elements)
    this.mutationObserver = new MutationObserver((mutations) => {
      if (mutations.some(m => m.addedNodes.length || m.removedNodes.length)) {
        this.wrapElementsInColumns();
      }
    });

    this.mutationObserver.observe(this.columnContainer.nativeElement, {
      childList: true,
      subtree: false
    });
  }

  ngOnDestroy(): void {
    // Clean up observer to prevent memory leaks
    this.mutationObserver?.disconnect();
  }

  private wrapElementsInColumns(): void {
    const container = this.columnContainer.nativeElement;
    
    // Get all elements that aren't already wrapped in x-col
    const unwrappedElements = Array.from(container.children).filter(
      el => !el.hasAttribute('x-col')
    );

    // Remove unwrapped elements temporarily
    unwrappedElements.forEach(el => container.removeChild(el));

    // Wrap each element in an x-col div and re-add to container
    unwrappedElements.forEach(el => {
      const colDiv = document.createElement('div');
      colDiv.setAttribute('x-col', '');
      colDiv.appendChild(el);
      container.appendChild(colDiv);
    });
  }
}

Step 2: Use the Component

Now you can use this component without any slot attributes—just place your elements/components directly inside it:

<!-- 2-column layout -->
<app-dynamic-row>
  <div>Content for first column</div>
  <app-my-custom-component></app-my-custom-component>
</app-dynamic-row>

<!-- 3-column layout -->
<app-dynamic-row>
  <p>Column 1</p>
  <div>Column 2 content</div>
  <app-another-component></app-another-component>
</app-dynamic-row>

<!-- Works with any number of columns! -->
<app-dynamic-row>
  <span>Col 1</span>
  <span>Col 2</span>
  <span>Col 3</span>
  <span>Col 4</span>
</app-dynamic-row>

How It Works

  • Content Projection: The <ng-content> tag captures all elements you place inside app-dynamic-row.
  • Initial Setup: In ngAfterContentInit, we first wrap all projected elements in x-col divs.
  • Dynamic Updates: We use a MutationObserver to watch for changes in the container's children (like adding or removing elements after initialization). When changes happen, we re-wrap any new unwrapped elements.
  • Avoid Duplicate Wrapping: We filter out elements that are already in an x-col div to prevent nesting them multiple times.

This approach is flexible, works with both plain HTML elements and Angular components, and adapts automatically to the number of items you project.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:57:29