在Angular 2中如何检查<ng-content>是否为空?

时间:2016-01-30 21:15:34

标签: javascript angular

假设我有一个组件:

@Component({
    selector: 'MyContainer',
    template: `
    <div class="container">
        <!-- some html skipped -->
        <ng-content></ng-content>
        <span *ngIf="????">Display this if ng-content is empty!</span>
        <!-- some html skipped -->
    </div>`
})
export class MyContainer {
}

现在,如果此组件的<ng-content>为空,我想显示一些默认内容。如果不直接访问DOM,有没有简单的方法呢?

12 个答案:

答案 0 :(得分:68)

ng-content之类的HTML元素中包装div以获取对其的本地引用,然后将ngIf表达式绑定到ref.children.length == 0

template: `<div #ref><ng-content></ng-content></div> 
           <span *ngIf="ref.nativeElement.childNodes.length == 0">
              Display this if ng-content is empty!
           </span>`

答案 1 :(得分:11)

@pixelbits答案中有些遗漏。我们不仅需要检查children属性,因为父模板中的任何换行符或空格都会导致children元素带有空白文本\换行符。 最好检查一下.innerHTML.trim()

工作示例:

<span #ref><ng-content></ng-content></span>
<span *ngIf="!ref.innerHTML.trim()">
    Content if empty
</span>

答案 2 :(得分:8)

注入内容时添加引用变量:

<div #content>Some Content</div>

并在您的组件类中使用@ContentChild()

获取对注入内容的引用
@ContentChild('content') content: ElementRef;

因此,在组件模板中,您可以检查内容变量是否具有值

<div>
  <ng-content></ng-content>
  <span *ngIf="!content">
    Display this if ng-content is empty!
  </span>    
</div> 

答案 3 :(得分:8)

这是CSS解决方案。 如果ng-content中未设置默认组件,则可以提供默认组件。由于他们是我的兄弟姐妹,因此可以这样解决。

自IE 9起兼容,部分自IE7 / 8起兼容:https://caniuse.com/#feat=css-sel3

HTML

<div class="my-custom-component-content-wrapper">
    <ng-content select="my-custom-component"></ng-content>
</div>
<my-custom-component>
    This shows something default.
</my-custom-component>

CSS

.my-custom-component-content-wrapper:not(:empty) + my-custom-component {
    display: none;
}

答案 4 :(得分:5)

注入elementRef: ElementRef并检查elementRef.nativeElement是否有孩子。这可能仅适用于encapsulation: ViewEncapsulation.Native

换行<ng-content>标记并检查它是否有子项。这不适用于encapsulation: ViewEncapsulation.Native

<div #contentWrapper>
  <ng-content></ng-content>
</div>

并检查它是否有孩子

@ViewChild('contentWrapper') contentWrapper;

ngAfterViewInit() {
  contentWrapper.nativeElement.childNodes...
}

(未经测试)

答案 5 :(得分:5)

如果要显示默认内容,为什么不使用CSS中的“独生子”选择器。

https://www.w3schools.com/cssref/sel_only-child.asp

例如: HTML

<div>
  <ng-content></ng-content>
  <div class="default-content">I am deafult</div>
</div>

css

.default-content:not(:only-child) {
   display: none;
}

答案 6 :(得分:2)

我已经通过使用 @ContentChildren 装饰器实现了一个解决方案,它在某种程度上类似于@Lerner的答案。

根据docs,此装饰器:

从内容DOM获取元素或指令的QueryList。每当添加,删除或移动子元素时,查询列表都会被更新,并且查询列表中可观察到的更改将发出新值。

因此,父组件中的必要代码将是:

<app-my-component>
  <div #myComponentContent>
    This is my component content
  </div>
</app-my-component>

在组件类中:

@ContentChildren('myComponentContent') content: QueryList<ElementRef>;

然后,在组件模板中:

<div class="container">
  <ng-content></ng-content>
  <span *ngIf="*ngIf="!content.length""><em>Display this if ng-content is empty!</em></span>
</div>

完整示例https://stackblitz.com/edit/angular-jjjdqb

我发现此解决方案在form-field组件的matSuffix的角度组件中实现。

在稍后注入组件的内容的情况下, 应用程序初始化后,我们还可以通过订阅changes事件来使用响应式实现QueryList

export class MyComponentComponent implements AfterContentInit, OnDestroy {
  private _subscription: Subscription;
  public hasContent: boolean;

  @ContentChildren('myComponentContent') content: QueryList<ElementRef>;

  constructor() {}

  ngAfterContentInit(): void {
    this.hasContent = (this.content.length > 0);
    this._subscription = this.content.changes.subscribe(() => {
      // do something when content updates
      //
      this.hasContent = (this.content.length > 0);
    });
  }

  ngOnDestroy() {
    this._subscription.unsubscribe();
  }

}

完整示例https://stackblitz.com/edit/angular-essvnq

答案 7 :(得分:2)

使用Angular 10时,它略有变化。您将使用:

<div #ref><ng-content></ng-content></div> 
<span *ngIf="ref.children.length == 0">
  Display this if ng-content is empty!
</span>

答案 8 :(得分:1)

就我而言,我必须隐藏空白ng-content的父项:

<span class="ml-1 wrapper">
  <ng-content>
  </ng-content>
</span>

简单的CSS作品:

.wrapper {
  display: inline-block;

  &:empty {
    display: none;
  }
}

答案 9 :(得分:1)

在 Angular 12 中,控制台会为我报告以下内容:

<块引用>

“HTMLElement”类型不存在属性“nativeElement”

似乎存在可以用于这种情况的特定属性 childElementCount

因此,我成功地使用了它,它不会将动态内容包装到其他元素/标签中:

<div class="container">
  <!-- some html skipped -->

  <ng-container #someContent>
    <ng-content></ng-content>
  </ng-container>
  <span 
    *ngIf="
      someContent.childElementCount === undefined || 
      someContent.childElementCount === 0
    "
  >
    Display this if ng-content is empty!
  </span>

  <!-- some html skipped -->
</div>

答案 10 :(得分:0)

<ng-content #ref></ng-content> 显示错误“ref”未声明。 以下内容适用于 Angular 11(也可能是 10):

<div #ref><ng-content></ng-content></div>
  <ng-container *ngIf="!ref.hasChildNodes()">
       Default Content
  </ng-container>

答案 11 :(得分:0)

在 angular 11 中我使用它并且工作正常。

模板文件:

 <h3 class="card-label" #titleBlock>
      <ng-content select="[title]" ></ng-content>
 </h3>

组件:

@ViewChild('titleBlock') titleBlock: ElementRef;
hasTitle: boolean;


ngAfterViewInit(): void {
    if (this.titleBlock && this.titleBlock.nativeElement.innerHTML.trim().length > 0)
    {
        this.hasTitle=  true;
    }
    else
    {
       this.hasTitle=  false;
    }
}