In Angular 2 how to check whether is empty?











up vote
56
down vote

favorite
10












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?










share|improve this question




















  • 1




    Possible duplicate of How to check whether ng-content exists
    – titusfx
    Sep 22 '17 at 15:56










  • FYI, I know the accepted answer works, but I think it's better style to pass in a "useDefault" type input parameter to components, defaulted to false.
    – bryan60
    Oct 31 '17 at 13:51















up vote
56
down vote

favorite
10












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?










share|improve this question




















  • 1




    Possible duplicate of How to check whether ng-content exists
    – titusfx
    Sep 22 '17 at 15:56










  • FYI, I know the accepted answer works, but I think it's better style to pass in a "useDefault" type input parameter to components, defaulted to false.
    – bryan60
    Oct 31 '17 at 13:51













up vote
56
down vote

favorite
10









up vote
56
down vote

favorite
10






10





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?










share|improve this question















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?







javascript angular






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 31 '17 at 13:41









Antikhippe

3,2581931




3,2581931










asked Jan 30 '16 at 21:15









Slawomir Dadas

4981815




4981815








  • 1




    Possible duplicate of How to check whether ng-content exists
    – titusfx
    Sep 22 '17 at 15:56










  • FYI, I know the accepted answer works, but I think it's better style to pass in a "useDefault" type input parameter to components, defaulted to false.
    – bryan60
    Oct 31 '17 at 13:51














  • 1




    Possible duplicate of How to check whether ng-content exists
    – titusfx
    Sep 22 '17 at 15:56










  • FYI, I know the accepted answer works, but I think it's better style to pass in a "useDefault" type input parameter to components, defaulted to false.
    – bryan60
    Oct 31 '17 at 13:51








1




1




Possible duplicate of How to check whether ng-content exists
– titusfx
Sep 22 '17 at 15:56




Possible duplicate of How to check whether ng-content exists
– titusfx
Sep 22 '17 at 15:56












FYI, I know the accepted answer works, but I think it's better style to pass in a "useDefault" type input parameter to components, defaulted to false.
– bryan60
Oct 31 '17 at 13:51




FYI, I know the accepted answer works, but I think it's better style to pass in a "useDefault" type input parameter to components, defaulted to false.
– bryan60
Oct 31 '17 at 13:51












5 Answers
5






active

oldest

votes

















up vote
62
down vote



accepted










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.nativeElement.childNodes.length == 0">
Display this if ng-content is empty!
</span>`





share|improve this answer



















  • 10




    Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
    – Astronaut
    Jan 11 '17 at 18:53






  • 8




    It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
    – parliament
    Jan 16 '17 at 8:22








  • 4




    There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
    – eppsilon
    Jan 23 '17 at 18:54








  • 3




    I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
    – Dustin Cleveland
    May 8 '17 at 14:25






  • 2




    Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
    – Romain Bruckert
    Oct 31 '17 at 15:41


















up vote
8
down vote













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 textlinebreaks.
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>





share|improve this answer

















  • 1




    best answer for me :)
    – Kamil Kiełczewski
    Sep 19 at 13:27


















up vote
5
down vote













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)






share|improve this answer

















  • 3




    I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
    – Cody
    Aug 30 '17 at 17:47








  • 3




    @Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
    – Günter Zöchbauer
    Aug 30 '17 at 18:05






  • 2




    Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
    – Cody
    Aug 30 '17 at 22:04








  • 2




    @Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
    – Günter Zöchbauer
    Aug 31 '17 at 3:19






  • 2




    Not exposing this in the API is the real anti-pattern :-(
    – Simon_Weaver
    Jun 15 at 21:24


















up vote
2
down vote













Here is a CSS solution.
This could provide a default component if none was set in the ng-content. As they are siblings in my case, one could solve it like this.



Which is compatible since IE 9 and partially since 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;
}





share|improve this answer























  • By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
    – jpavel
    Dec 4 at 13:38


















up vote
1
down vote













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>





share|improve this answer





















  • This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
    – CarbonDry
    Oct 2 at 11:47










  • The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
    – pixelbits
    Oct 3 at 2:53













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f35107211%2fin-angular-2-how-to-check-whether-ng-content-is-empty%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























5 Answers
5






active

oldest

votes








5 Answers
5






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
62
down vote



accepted










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.nativeElement.childNodes.length == 0">
Display this if ng-content is empty!
</span>`





share|improve this answer



















  • 10




    Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
    – Astronaut
    Jan 11 '17 at 18:53






  • 8




    It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
    – parliament
    Jan 16 '17 at 8:22








  • 4




    There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
    – eppsilon
    Jan 23 '17 at 18:54








  • 3




    I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
    – Dustin Cleveland
    May 8 '17 at 14:25






  • 2




    Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
    – Romain Bruckert
    Oct 31 '17 at 15:41















up vote
62
down vote



accepted










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.nativeElement.childNodes.length == 0">
Display this if ng-content is empty!
</span>`





share|improve this answer



















  • 10




    Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
    – Astronaut
    Jan 11 '17 at 18:53






  • 8




    It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
    – parliament
    Jan 16 '17 at 8:22








  • 4




    There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
    – eppsilon
    Jan 23 '17 at 18:54








  • 3




    I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
    – Dustin Cleveland
    May 8 '17 at 14:25






  • 2




    Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
    – Romain Bruckert
    Oct 31 '17 at 15:41













up vote
62
down vote



accepted







up vote
62
down vote



accepted






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.nativeElement.childNodes.length == 0">
Display this if ng-content is empty!
</span>`





share|improve this answer














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.nativeElement.childNodes.length == 0">
Display this if ng-content is empty!
</span>`






share|improve this answer














share|improve this answer



share|improve this answer








edited Aug 23 at 0:42









dudewad

4,78721934




4,78721934










answered Jan 31 '16 at 7:32









pixelbits

39.6k1065101




39.6k1065101








  • 10




    Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
    – Astronaut
    Jan 11 '17 at 18:53






  • 8




    It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
    – parliament
    Jan 16 '17 at 8:22








  • 4




    There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
    – eppsilon
    Jan 23 '17 at 18:54








  • 3




    I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
    – Dustin Cleveland
    May 8 '17 at 14:25






  • 2




    Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
    – Romain Bruckert
    Oct 31 '17 at 15:41














  • 10




    Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
    – Astronaut
    Jan 11 '17 at 18:53






  • 8




    It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
    – parliament
    Jan 16 '17 at 8:22








  • 4




    There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
    – eppsilon
    Jan 23 '17 at 18:54








  • 3




    I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
    – Dustin Cleveland
    May 8 '17 at 14:25






  • 2




    Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
    – Romain Bruckert
    Oct 31 '17 at 15:41








10




10




Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
– Astronaut
Jan 11 '17 at 18:53




Is there no alternative way to this? Because this is ugly, compared to Aurelia fallback slots
– Astronaut
Jan 11 '17 at 18:53




8




8




It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
– parliament
Jan 16 '17 at 8:22






It's safer to use ref.children.length. childNodes will contain text nodes if you format your html with spaces or new lines, but children will still be empty.
– parliament
Jan 16 '17 at 8:22






4




4




There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
– eppsilon
Jan 23 '17 at 18:54






There is a feature request for a better method on the Angular issue tracker: github.com/angular/angular/issues/12530 (might be worth adding a +1 there).
– eppsilon
Jan 23 '17 at 18:54






3




3




I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
– Dustin Cleveland
May 8 '17 at 14:25




I was about to post that this didn't seem to be working until I realized that I used the example of ref.childNodes.length == 0 instead of ref.children.length == 0. It would help a bunch if you could edit the answer to be consistent. Easy mistake, not bashing you. :)
– Dustin Cleveland
May 8 '17 at 14:25




2




2




Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
– Romain Bruckert
Oct 31 '17 at 15:41




Its even ref.nativeElement.childNodes.length. Could this answer be edited please?
– Romain Bruckert
Oct 31 '17 at 15:41












up vote
8
down vote













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 textlinebreaks.
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>





share|improve this answer

















  • 1




    best answer for me :)
    – Kamil Kiełczewski
    Sep 19 at 13:27















up vote
8
down vote













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 textlinebreaks.
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>





share|improve this answer

















  • 1




    best answer for me :)
    – Kamil Kiełczewski
    Sep 19 at 13:27













up vote
8
down vote










up vote
8
down vote









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 textlinebreaks.
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>





share|improve this answer












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 textlinebreaks.
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>






share|improve this answer












share|improve this answer



share|improve this answer










answered Feb 14 at 13:17









lfoma

8111




8111








  • 1




    best answer for me :)
    – Kamil Kiełczewski
    Sep 19 at 13:27














  • 1




    best answer for me :)
    – Kamil Kiełczewski
    Sep 19 at 13:27








1




1




best answer for me :)
– Kamil Kiełczewski
Sep 19 at 13:27




best answer for me :)
– Kamil Kiełczewski
Sep 19 at 13:27










up vote
5
down vote













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)






share|improve this answer

















  • 3




    I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
    – Cody
    Aug 30 '17 at 17:47








  • 3




    @Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
    – Günter Zöchbauer
    Aug 30 '17 at 18:05






  • 2




    Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
    – Cody
    Aug 30 '17 at 22:04








  • 2




    @Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
    – Günter Zöchbauer
    Aug 31 '17 at 3:19






  • 2




    Not exposing this in the API is the real anti-pattern :-(
    – Simon_Weaver
    Jun 15 at 21:24















up vote
5
down vote













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)






share|improve this answer

















  • 3




    I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
    – Cody
    Aug 30 '17 at 17:47








  • 3




    @Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
    – Günter Zöchbauer
    Aug 30 '17 at 18:05






  • 2




    Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
    – Cody
    Aug 30 '17 at 22:04








  • 2




    @Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
    – Günter Zöchbauer
    Aug 31 '17 at 3:19






  • 2




    Not exposing this in the API is the real anti-pattern :-(
    – Simon_Weaver
    Jun 15 at 21:24













up vote
5
down vote










up vote
5
down vote









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)






share|improve this answer












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)







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 30 '16 at 22:27









Günter Zöchbauer

309k64911860




309k64911860








  • 3




    I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
    – Cody
    Aug 30 '17 at 17:47








  • 3




    @Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
    – Günter Zöchbauer
    Aug 30 '17 at 18:05






  • 2




    Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
    – Cody
    Aug 30 '17 at 22:04








  • 2




    @Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
    – Günter Zöchbauer
    Aug 31 '17 at 3:19






  • 2




    Not exposing this in the API is the real anti-pattern :-(
    – Simon_Weaver
    Jun 15 at 21:24














  • 3




    I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
    – Cody
    Aug 30 '17 at 17:47








  • 3




    @Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
    – Günter Zöchbauer
    Aug 30 '17 at 18:05






  • 2




    Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
    – Cody
    Aug 30 '17 at 22:04








  • 2




    @Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
    – Günter Zöchbauer
    Aug 31 '17 at 3:19






  • 2




    Not exposing this in the API is the real anti-pattern :-(
    – Simon_Weaver
    Jun 15 at 21:24








3




3




I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
– Cody
Aug 30 '17 at 17:47






I downvoted this because of the use of @ViewChild. While "Legal", ViewChild should not be used for accessing child-nodes within a template. This is an antipattern because, while parents may know about children, they should not Couple to them as it usually leads to Pathological Coupling; a more appropriate form of data-transport or request-handling is to use event-driven methodologies.
– Cody
Aug 30 '17 at 17:47






3




3




@Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
– Günter Zöchbauer
Aug 30 '17 at 18:05




@Cody thanks for posting a comment to your downvote. Actually I don't follow your argumentation. The template and the components class are a single unit - a component. I don't see why accessing the template from the code should be an antipattern. Angular (2/4) has almost nothing in common with AngularJS except that both are web frameworks and the name.
– Günter Zöchbauer
Aug 30 '17 at 18:05




2




2




Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
– Cody
Aug 30 '17 at 22:04






Gunter, you make two really good points. Angular should not necessarily hatch with a stigma from the ways of AngularJS. But I'd mark that the first point (and those I've made above) fall toward the philosophical gutter of engineering. That said, I've become something of an expert on Software Coupling and I'd advise against [at least heavy] use of @ViewChild. Thanks for adding some balance to my comments -- I find both of our comments just as worthy of consideration as the other.
– Cody
Aug 30 '17 at 22:04






2




2




@Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
– Günter Zöchbauer
Aug 31 '17 at 3:19




@Cody perhaps your strong opinion about @ViewChild() comes from the name. "Children" aren't necessarily children, they are just the declarative part of the component (as I see it). If the component instances created for this markup are accesses, this if of course a different story, because it would require knowledge about at least their public interface and this would actually create tight coupling. This is a very interesting discussion. It worries me that I don't have enough time to think about such matters because with such frameworks too often time is burned to find any way at all.
– Günter Zöchbauer
Aug 31 '17 at 3:19




2




2




Not exposing this in the API is the real anti-pattern :-(
– Simon_Weaver
Jun 15 at 21:24




Not exposing this in the API is the real anti-pattern :-(
– Simon_Weaver
Jun 15 at 21:24










up vote
2
down vote













Here is a CSS solution.
This could provide a default component if none was set in the ng-content. As they are siblings in my case, one could solve it like this.



Which is compatible since IE 9 and partially since 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;
}





share|improve this answer























  • By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
    – jpavel
    Dec 4 at 13:38















up vote
2
down vote













Here is a CSS solution.
This could provide a default component if none was set in the ng-content. As they are siblings in my case, one could solve it like this.



Which is compatible since IE 9 and partially since 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;
}





share|improve this answer























  • By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
    – jpavel
    Dec 4 at 13:38













up vote
2
down vote










up vote
2
down vote









Here is a CSS solution.
This could provide a default component if none was set in the ng-content. As they are siblings in my case, one could solve it like this.



Which is compatible since IE 9 and partially since 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;
}





share|improve this answer














Here is a CSS solution.
This could provide a default component if none was set in the ng-content. As they are siblings in my case, one could solve it like this.



Which is compatible since IE 9 and partially since 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;
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 at 7:29

























answered Nov 11 at 10:20









Stefan Rein

2,21622020




2,21622020












  • By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
    – jpavel
    Dec 4 at 13:38


















  • By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
    – jpavel
    Dec 4 at 13:38
















By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
– jpavel
Dec 4 at 13:38




By far this was the best solution for my use case. I wasn't remembering we had an empty css pseudoclass
– jpavel
Dec 4 at 13:38










up vote
1
down vote













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>





share|improve this answer





















  • This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
    – CarbonDry
    Oct 2 at 11:47










  • The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
    – pixelbits
    Oct 3 at 2:53

















up vote
1
down vote













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>





share|improve this answer





















  • This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
    – CarbonDry
    Oct 2 at 11:47










  • The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
    – pixelbits
    Oct 3 at 2:53















up vote
1
down vote










up vote
1
down vote









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>





share|improve this answer












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>






share|improve this answer












share|improve this answer



share|improve this answer










answered Mar 29 at 19:06









Lerner

312414




312414












  • This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
    – CarbonDry
    Oct 2 at 11:47










  • The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
    – pixelbits
    Oct 3 at 2:53




















  • This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
    – CarbonDry
    Oct 2 at 11:47










  • The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
    – pixelbits
    Oct 3 at 2:53


















This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
– CarbonDry
Oct 2 at 11:47




This is the cleanest, and much better answer. It supports the ContentChild API out of the box. Can't understand why the top answer got so many votes.
– CarbonDry
Oct 2 at 11:47












The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
– pixelbits
Oct 3 at 2:53






The OP asked for whether or not ngContent is empty - this means <MyContainer></MyContainer>. Your solution expects users to create a sub-element under MyContainer: <MyContainer><div #content></div></MyContainer>. While this is a possibility, I would not say this is superior.
– pixelbits
Oct 3 at 2:53




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f35107211%2fin-angular-2-how-to-check-whether-ng-content-is-empty%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma