Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

What is Ng-content in angular?

The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.

What is the difference between Ng-content ng-container and ng-template?

To sum up, ng-content is used to display children in a template, ng-container is used as a non-rendered container to avoid having to add a span or a div, and ng-template allows you to group some content that is not rendered directly but can be used in other places of your template or you code.

Can we style ng-content?

Use the :host /deep/ selector. If you want to use the shadow DOM polyfill and style your components using the style or styleUrls attribute of the Component decorator, select the element with :host , then ignore the shadow DOM polyfill with the /deep/ child selector. :host will select the element.

Is Ng-content a directive?

ng-container is an extremely simple directive that allows you to group elements in a template but doesn't itself get rendered in the DOM (but what it contains does). It just becomes a comment: It is especially helpful when you want to apply two structural directives to the same element.


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.


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>

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>

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('content') content: ElementRef;

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

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

Inject elementRef: ElementRef and check if elementRef.nativeElement has any children. This might only work with encapsulation: ViewEncapsulation.Native.

Wrap the <ng-content> tag and check if it has children. This doesn't work with 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)


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

https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child

for eg: HTML

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

css

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