In Angular 2 how to check whether is empty?
up vote
56
down vote
favorite
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
add a comment |
up vote
56
down vote
favorite
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
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
add a comment |
up vote
56
down vote
favorite
up vote
56
down vote
favorite
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
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
javascript angular
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
add a comment |
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
add a comment |
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>`
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 useref.children.length
. childNodes will containtext
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 ofref.childNodes.length == 0
instead ofref.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 evenref.nativeElement.childNodes.length
. Could this answer be edited please?
– Romain Bruckert
Oct 31 '17 at 15:41
|
show 7 more comments
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>
1
best answer for me :)
– Kamil Kiełczewski
Sep 19 at 13:27
add a comment |
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)
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
|
show 4 more comments
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;
}
By far this was the best solution for my use case. I wasn't remembering we had anempty
css pseudoclass
– jpavel
Dec 4 at 13:38
add a comment |
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>
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
add a comment |
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>`
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 useref.children.length
. childNodes will containtext
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 ofref.childNodes.length == 0
instead ofref.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 evenref.nativeElement.childNodes.length
. Could this answer be edited please?
– Romain Bruckert
Oct 31 '17 at 15:41
|
show 7 more comments
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>`
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 useref.children.length
. childNodes will containtext
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 ofref.childNodes.length == 0
instead ofref.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 evenref.nativeElement.childNodes.length
. Could this answer be edited please?
– Romain Bruckert
Oct 31 '17 at 15:41
|
show 7 more comments
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>`
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>`
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 useref.children.length
. childNodes will containtext
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 ofref.childNodes.length == 0
instead ofref.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 evenref.nativeElement.childNodes.length
. Could this answer be edited please?
– Romain Bruckert
Oct 31 '17 at 15:41
|
show 7 more comments
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 useref.children.length
. childNodes will containtext
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 ofref.childNodes.length == 0
instead ofref.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 evenref.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
|
show 7 more comments
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>
1
best answer for me :)
– Kamil Kiełczewski
Sep 19 at 13:27
add a comment |
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>
1
best answer for me :)
– Kamil Kiełczewski
Sep 19 at 13:27
add a comment |
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>
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>
answered Feb 14 at 13:17
lfoma
8111
8111
1
best answer for me :)
– Kamil Kiełczewski
Sep 19 at 13:27
add a comment |
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
add a comment |
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)
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
|
show 4 more comments
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)
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
|
show 4 more comments
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)
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)
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
|
show 4 more comments
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
|
show 4 more comments
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;
}
By far this was the best solution for my use case. I wasn't remembering we had anempty
css pseudoclass
– jpavel
Dec 4 at 13:38
add a comment |
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;
}
By far this was the best solution for my use case. I wasn't remembering we had anempty
css pseudoclass
– jpavel
Dec 4 at 13:38
add a comment |
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;
}
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;
}
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 anempty
css pseudoclass
– jpavel
Dec 4 at 13:38
add a comment |
By far this was the best solution for my use case. I wasn't remembering we had anempty
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
add a comment |
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>
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
add a comment |
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>
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
add a comment |
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>
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>
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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