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

Angular嵌套子组件内容投影问题:无法获取CustomTemplate实例

问题原因与解决方案

核心问题:混淆了@ContentChildren与@ViewChildren的用途

你当前使用@ContentChildren查询CustomTemplate实例,但@ContentChildren仅用于查询外部通过ng-content传入组件的内容投影元素/指令,而你的customTemplate指令是直接写在父组件自身模板中的,不属于内容投影范畴,因此查询结果为空。

修复步骤

1. 将@ContentChildren替换为@ViewChildren

@ViewChildren用于查询组件自身模板内的元素、指令或组件实例,正好匹配你的场景:

import { Component, AfterViewInit, ViewChildren, QueryList } from '@angular/core';
import { CustomTemplate } from './custom-template.directive';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit {
  // 替换@ContentChildren为@ViewChildren
  @ViewChildren(CustomTemplate) public templates?: QueryList<CustomTemplate>;

  ngAfterViewInit(): void {
    console.log(this.templates); // 现在能正常获取到CustomTemplate实例列表
  }
}

2. 优化指令,直接关联内部模板

为了更方便地传递模板到子组件,建议在CustomTemplate指令中直接获取内部的ng-template实例:

import { Directive, ElementRef, Input, ContentChild, TemplateRef } from '@angular/core';

@Directive({ selector: '[customTemplate]' })
export class CustomTemplate {
  @Input() public field!: string;
  // 通过模板引用变量获取内部ng-template
  @ContentChild('myTemplate') public templateRef?: TemplateRef<any>;

  constructor(public el: ElementRef) {}
}

3. 传递模板到嵌套子组件

修改父组件模板,给ng-template添加模板引用变量,并通过输入属性将模板列表传递给子组件:

<div customTemplate field="test1">
  <ng-template #myTemplate>
    <p>Some text here T1</p>
  </ng-template>
</div>
<div customTemplate field="test2">
  <ng-template #myTemplate>
    <p>Some text here T2</p>
  </ng-template>
</div>
<Child1 [templates]="templates"></Child1>

子组件接收并渲染模板

Child1中转模板:

import { Component, Input } from '@angular/core';
import { CustomTemplate } from './custom-template.directive';
import { QueryList } from '@angular/core';

@Component({
  selector: 'Child1',
  template: `<Child2 [templates]="templates"></Child2>`
})
export class Child1Component {
  @Input() templates?: QueryList<CustomTemplate>;
}

Child2渲染模板:

import { Component, Input } from '@angular/core';
import { CustomTemplate } from './custom-template.directive';
import { QueryList } from '@angular/core';

@Component({
  selector: 'Child2',
  template: `
    <div *ngFor="let item of templates">
      <h4>Template for {{item.field}}</h4>
      <ng-container [ngTemplateOutlet]="item.templateRef"></ng-container>
    </div>
  `
})
export class Child2Component {
  @Input() templates?: QueryList<CustomTemplate>;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 14:48:15