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

Angular独立组件内容投影问题:@ContentChild无法渲染

解决Angular独立组件中@ContentChild配合内容投影的未定义错误

问题根源

你遇到的ERROR TypeError: Cannot read properties of undefined (reading 'tpl'),本质是**@ContentChild查询的指令实例在组件初始化时还未被赋值**,或者独立组件未正确导入依赖的自定义指令,导致模板中访问tpl属性时触发未定义错误。

具体修复步骤

1. 确保独立组件导入依赖指令

独立组件必须显式导入所需的自定义指令,否则Angular无法识别模板中的指令,导致@ContentChild查询不到目标实例:

@Component({
  selector: 'app-card',
  standalone: true,
  imports: [CardContentDirective], // 必须导入自定义模板指令
  template: `
    <div class="card">
      <ng-container [ngTemplateOutlet]="cardContent?.tpl"></ng-container>
    </div>
  `,
})
export class CardComponent {
  @ContentChild(CardContentDirective) cardContent?: CardContentDirective;
}

2. 使用可选链或ngIf避免未定义访问

在模板中通过**可选链操作符?.**直接保护访问,或者用*ngIf先判断实例是否存在,再渲染模板:

  • 方式一(可选链):
<ng-container [ngTemplateOutlet]="cardContent?.tpl"></ng-container>
  • 方式二(ngIf):
<ng-container *ngIf="cardContent" [ngTemplateOutlet]="cardContent.tpl"></ng-container>

3. 利用生命周期钩子确保查询完成

如果需要在组件逻辑中操作tpl,请在ngAfterViewInit钩子中处理——这是Angular完成视图初始化、@ContentChild实例被赋值的时机:

export class CardComponent implements AfterViewInit {
  @ContentChild(CardContentDirective) cardContent?: CardContentDirective;

  ngAfterViewInit() {
    // 此时可安全访问cardContent及tpl属性
    if (this.cardContent) {
      console.log('模板实例已加载:', this.cardContent.tpl);
    }
  }
}

4. 检查自定义指令的正确性

确保自定义指令正确注入TemplateRef,并暴露给父组件访问:

@Directive({
  selector: '[appCardContent]',
  standalone: true,
})
export class CardContentDirective {
  constructor(public tpl: TemplateRef<any>) {} // 必须public暴露tpl
}

最终使用示例

父组件中正常使用内容投影:

<app-card>
  <ng-template appCardContent>
    卡片1的自定义内容
  </ng-template>
</app-card>

<app-card>
  <ng-template appCardContent>
    卡片2的自定义内容
  </ng-template>
</app-card>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 06:27:36