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
相关产品推荐
相关产品推荐

