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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35107211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:17:20  来源:igfitidea点击:

In Angular 2 how to check whether <ng-content> is empty?

javascriptangular

提问by Slawomir Dadas

Suppose I have a component:

假设我有一个组件:

@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 {
}

Now, I would like to display some default content if <ng-content>for this component is empty. Is there an easy way to do this without accessing the DOM directly?

现在,如果<ng-content>此组件为空,我想显示一些默认内容。有没有一种简单的方法可以在不直接访问 DOM 的情况下做到这一点?

回答by pixelbits

Wrap ng-contentin an HTML element like a divto get a local reference to it, then bind the ngIfexpression to ref.children.length == 0:

包裹ng-content在像 a 这样的 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>`

回答by lfoma

There some missing in @pixelbits answer. We need to check not only childrenproperty, because any line breaks or spaces in parent template will cause childrenelement with blank text\linebreaks. Better to check .innerHTMLand .trim()it.

@pixelbits 答案中缺少一些内容。我们不仅需要检查children属性,因为父模板中的任何换行符或空格都会导致children元素出现空白文本\换行符。更好地检查.innerHTML.trim()它。

Working example:

工作示例:

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

回答by Lerner

When you inject the content add a reference variable:

当您注入内容时,添加一个引用变量:

<div #content>Some Content</div>

and in your component class get a reference to the injected content with @ContentChild()

并在您的组件类中使用 @ContentChild() 获取对注入内容的引用

@ContentChild('content') content: ElementRef;

so in your component template you can check if the content variable has a value

所以在你的组件模板中,你可以检查 content 变量是否有值

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

回答by Stefan Rein

EDIT 17.03.2020

编辑 17.03.2020

Pure CSS (2 solutions)

纯 CSS(2 个解决方案)

Provides default content if nothing is projected into ng-content.

如果没有任何内容投射到 ng-content 中,则提供默认内容。

Possible selectors:

可能的选择器:

  1. :only-childselector. See this post here: :only-child Selector

    This one require less code / markup. Support since IE 9: Can I Use :only-child

  2. :emptyselector. Just read further.

    Support from IE 9 and partially since IE 7/8: https://caniuse.com/#feat=css-sel3

  1. :only-child选择器。在这里看到这篇文章::only-child Selector

    这个需要更少的代码/标记。自 IE 9 起支持:我可以使用 :only-child

  2. :empty选择器。只需进一步阅读。

    来自 IE 9 和部分自 IE 7/8 的支持:https: //caniuse.com/#feat=css-sel3

HTML

HTML

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

CSS

CSS

.wrapper:not(:empty) + .default {
    display: none;
}


In case it's not working

如果它不起作用

Be aware of, that having at least one whitespace is considered to not beeing empty. Angular removes whitespace, but just in case if it is not:

请注意,至少有一个空格被认为不是空的。Angular 会删除空格,但以防万一:

<div class="wrapper"><!--
    --><ng-content select="my-component"></ng-content><!--
--></div>

or

或者

<div class="wrapper"><ng-content select="my-component"></ng-content</div>

回答by Günter Z?chbauer

Inject elementRef: ElementRefand check if elementRef.nativeElementhas any children. This might only work with encapsulation: ViewEncapsulation.Native.

注射elementRef: ElementRef并检查是否elementRef.nativeElement有儿童。这可能只适用于encapsulation: ViewEncapsulation.Native.

Wrap the <ng-content>tag and check if it has children. This doesn't work with encapsulation: ViewEncapsulation.Native.

包裹<ng-content>标签并检查它是否有孩子。这不适用于encapsulation: ViewEncapsulation.Native.

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

and check if it has any children

并检查它是否有任何孩子

@ViewChild('contentWrapper') contentWrapper;

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

(not tested)

(未测试)

回答by ecosystem31

If you want to display a default content why dont you just use the 'only-child' selector from css.

如果您想显示默认内容,为什么不使用 css 中的“only-child”选择器。

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

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

for eg: HTML

例如:HTML

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

css

css

.default-content {
   display: none;
}

.default-content:only-child {
   display: block;
}

回答by smg

In my case I have to hide parent of empty ng-content:

在我的情况下,我必须隐藏空 ng-content 的父级:

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

Simple css works:

简单的css工作:

.wrapper {
  display: inline-block;

  &:empty {
    display: none;
  }
}

回答by andreivictor

I've implemented a solution by using @ContentChildrendecorator, that is somehow similar to @Lerner's answer.

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

According to docs, this decorator:

根据docs,这个装饰器:

Get the QueryList of elements or directives from the content DOM. Any time a child element is added, removed, or moved, the query list will be updated, and the changes observable of the query list will emit a new value.

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

So the necessary code in the parent component will be:

所以父组件中必要的代码将是:

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

In the component class:

在组件类中:

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

Then, in component template:

然后,在组件模板中:

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

Full example: https://stackblitz.com/edit/angular-jjjdqb

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

I've found this solution implemented in angular components, for matSuffix, in the form-fieldcomponent.

我发现这个解决方案在 angular 组件中实现, for matSuffix,在form-field组件中。

In the situation when the content of the component is injected later on, afterthe app is initialised, we can also use a reactive implementation, by subscribing to the changesevent of the QueryList:

在稍后注入组件内容的情况下,应用程序初始化后,我们还可以使用反应式实现,通过订阅以下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();
  }

}

Full example: https://stackblitz.com/edit/angular-essvnq

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