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

Angular中如何在ng-content内容不存在时隐藏对应元素?

解决Angular中无内容时隐藏ng-content对应容器的问题

你当前的思路方向是对的,但有个关键问题:ng-content的内容投影是在ngAfterContentInit生命周期钩子之后才完成的,在ngOnInit里去判断innerHTML大概率会拿到空值,导致判断逻辑失效。下面给你几个更可靠的实现方案:

方案一:使用@ContentChild直接检测投影内容

这种方式直接检测是否存在带有title属性的投影元素,逻辑更直观清晰:

组件TS代码修改

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

@Component({
  selector: "card",
  templateUrl: "./card.component.html",
  styleUrls: ["./card.component.scss"]
})
export class CardComponent implements AfterContentInit {
  // 检测带有title属性的投影内容
  @ContentChild('titleContent', { static: false }) titleContent: ElementRef;
  hasTitle = false;

  ngAfterContentInit(): void {
    // 确认投影内容存在且非空白文本
    this.hasTitle = !!this.titleContent && (this.titleContent.nativeElement.textContent ?? '').trim() !== '';
  }
}

模板代码修改

给ng-content添加模板引用变量,方便TS逻辑检测:

<mat-card>
  <mat-card-header *ngIf="hasTitle">
    <mat-card-title>
      <ng-content select="[title]" #titleContent></ng-content>
    </mat-card-title>
  </mat-card-header>
  <mat-divider *ngIf="hasTitle"></mat-divider>
  <mat-card-content>
    <ng-content select="[content]"></ng-content>
  </mat-card-content>
</mat-card>

方案二:优化原有ViewChild方案(调整生命周期钩子)

如果你想保留原有的模板结构,只需要把判断逻辑从ngOnInit移到ngAfterContentInit,因为此时投影内容已经完全渲染完成:

组件TS代码修改

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

@Component({
  selector: "card",
  templateUrl: "./card.component.html",
  styleUrls: ["./card.component.scss"]
})
export class CardComponent implements OnInit, AfterContentInit {
  @ViewChild('title', {static: false}) titleRef: ElementRef;
  hasTitle = true;

  constructor() { }

  ngOnInit(): void { }

  ngAfterContentInit(): void {
    if ((this.titleRef.nativeElement.innerHTML ?? '').trim() === '') {
      this.hasTitle = false;
    }
  }
}

模板代码修改

把*ngIf的条件替换为hasTitle:

<mat-card>
  <mat-card-header #title *ngIf="hasTitle">
    <mat-card-title>
      <ng-content select="[title]"></ng-content>
    </mat-card-title>
  </mat-card-header>
  <mat-divider *ngIf="hasTitle"></mat-divider>
  <mat-card-content>
    <ng-content select="[content]"></ng-content>
  </mat-card-content>
</mat-card>

方案三:纯模板层面判断(仅作参考)

利用Angular内部的isEmpty属性可以实现无TS逻辑的判断,但不推荐在生产环境使用——因为这个属性属于未公开的内部API,未来Angular版本可能会变更:

<mat-card>
  <mat-card-header *ngIf="!titleContent.isEmpty">
    <mat-card-title>
      <ng-content select="[title]" #titleContent></ng-content>
    </mat-card-title>
  </mat-card-header>
  <mat-divider *ngIf="!titleContent.isEmpty"></mat-divider>
  <mat-card-content>
    <ng-content select="[content]"></ng-content>
  </mat-card-content>
</mat-card>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:47:39