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.
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.
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.
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, asnativeElement
isundefined
nowadays.
EDIT 17.03.2020
Provides default content if nothing is projected into ng-content.
: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
:empty
selector. Just read further.
Support from IE 9 and partially since IE 7/8: https://caniuse.com/#feat=css-sel3
<div class="wrapper">
<ng-content select="my-component"></ng-content>
</div>
<div class="default">
This shows something default.
</div>
.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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With