Angular中判断ng-content是否为空,实现模板切换渲染
解决方案
你的核心问题在于:直接判断TemplateRef是否存在是无效的——这两个模板引用在组件初始化后始终存在,和ng-content是否有投影内容无关。要实现需求,必须先检测select属性对应的投影内容是否存在,再决定渲染哪个模板。
方法一:子组件内部封装逻辑(推荐)
在子组件中添加内容检测逻辑,自动判断并渲染对应模板,无需父组件额外处理:
- 修改子组件代码,添加内容检测:
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; } }
- 父组件正常使用即可,无需额外判断:
<app-custom-select> <div option>默认展示内容</div> <!-- 可选:添加select属性的内容,存在时会优先渲染 --> <div select>选中状态专属内容</div> </app-custom-select>
方法二:父组件控制渲染逻辑
如果需要父组件自行控制,可在子组件暴露检测状态和模板引用,父组件根据状态选择模板:
- 子组件暴露公共属性:
// 子组件代码(同方法一,仅需确保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; } }
- 父组件通过模板引用获取状态并渲染:
<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
相关产品推荐
相关产品推荐

