How to check whether <ng-content> is empty? (in Angular 2+ till now)

Solution 1:

Wrap ng-content in an HTML element like a div to get a local reference to it, then bind the ngIf expression to ref.children.length == 0:

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

Updated for Angular 12; old logic ("ref.nativeElement.childNodes.length") gives error, as nativeElement is undefined nowadays.

Solution 2:

EDIT 17.03.2020

Pure CSS (2 solutions)

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

Possible selectors:

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

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

  2. :empty selector. Just read further.

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

HTML

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

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:

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

or

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

Solution 3:

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

Working example:

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