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

Angular中判断ng-content是否为空,实现模板切换渲染

解决方案

你的核心问题在于:直接判断TemplateRef是否存在是无效的——这两个模板引用在组件初始化后始终存在,和ng-content是否有投影内容无关。要实现需求,必须先检测select属性对应的投影内容是否存在,再决定渲染哪个模板。

方法一:子组件内部封装逻辑(推荐)

在子组件中添加内容检测逻辑,自动判断并渲染对应模板,无需父组件额外处理:

  1. 修改子组件代码,添加内容检测:
import { Component, ViewChild, TemplateRef, ContentChild, AfterContentInit } from '@angular/core';

@Component({
  selector: 'app-custom-select',
  template: `
    <ng-template #optionContent>
      <ng-content select="[option]"></ng-content>
    </ng-template>

    <ng-template #selectContent>
      <ng-content select="[select]"></ng-content>
    </ng-template>

    <!-- 根据检测结果自动选择模板 -->
    <ng-container [ngTemplateOutlet]="hasSelectContent ? selectContent : optionContent"></ng-container>
  `
})
export class CustomSelectComponent implements AfterContentInit {
  @ViewChild('optionContent') optionContent: TemplateRef<unknown>; 
  @ViewChild('selectContent') selectContent: TemplateRef<unknown>;

  // 检测带有[select]属性的投影内容
  @ContentChild(ElementRef, { selector: '[select]', static: false }) private selectProjection: ElementRef;
  hasSelectContent = false;

  ngAfterContentInit() {
    // 判断投影内容是否存在
    this.hasSelectContent = !!this.selectProjection;
    // 如果支持多元素投影,改用@ContentChildren:
    // @ContentChildren(ElementRef, { selector: '[select]' }) private selectProjections: QueryList<ElementRef>;
    // this.hasSelectContent = this.selectProjections.length > 0;
  }
}
  1. 父组件正常使用即可,无需额外判断:
<app-custom-select>
  <div option>默认展示内容</div>
  <!-- 可选:添加select属性的内容,存在时会优先渲染 -->
  <div select>选中状态专属内容</div>
</app-custom-select>

方法二:父组件控制渲染逻辑

如果需要父组件自行控制,可在子组件暴露检测状态和模板引用,父组件根据状态选择模板:

  1. 子组件暴露公共属性:
// 子组件代码(同方法一,仅需确保hasSelectContent、optionContent、selectContent为公共属性)
export class CustomSelectComponent implements AfterContentInit {
  // 保持属性为公共(默认public)
  @ViewChild('optionContent') optionContent: TemplateRef<unknown>; 
  @ViewChild('selectContent') selectContent: TemplateRef<unknown>;

  @ContentChild(ElementRef, { selector: '[select]', static: false }) private selectProjection: ElementRef;
  hasSelectContent = false;

  ngAfterContentInit() {
    this.hasSelectContent = !!this.selectProjection;
  }
}
  1. 父组件通过模板引用获取状态并渲染:
<app-custom-select #customSelect>
  <div option>默认展示内容</div>
  <div select>选中状态专属内容</div>
</app-custom-select>

<!-- 父组件中根据状态选择模板 -->
<ng-container 
  [ngTemplateOutlet]="customSelect.hasSelectContent ? customSelect.selectContent : customSelect.optionContent"
></ng-container>

补充说明

  • 若投影内容是动态加载的,可在ngAfterContentChecked钩子中更新hasSelectContent状态,确保动态变化能被检测到。
  • 不要直接判断TemplateRef是否存在,因为模板引用在组件初始化后就会一直存在,和投影内容无关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:20:21