Suppose i have simple Bootstrap panel component with multiple transclusion slots. Template example:
<div class="panel panel-default">   <div class="panel-heading">     <ng-content select="my-panel-heading"></ng-content>   </div>   <div class="panel-body">     <ng-content select="my-panel-content"></ng-content>   </div> </div>   I want to make panel-heading optional. How do i hide <div class="panel-heading"> element, if there is no content provided for <ng-content select="my-panel-heading"></ng-content>
The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.
Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.
ng-container serves as a container for elements which can also accept structural directives but is not rendered to the DOM, while ng-template allows you to create template content that is not rendered until you specifically (conditionally or directly) add it to the DOM.
ng-content is an important concept to create reusable and flexible components. With the help of ng-content content can be projected by a parent component into a predefined slot. In some cases, you want to apply some styles to the projected content.
If you have a parent element of <ng-content> with a template variable (#panelHeading)
<div class="panel panel-default">   <div class="panel-heading" #panelHeading [hidden]="!showHeading">     <ng-content select="my-panel-heading"></ng-content>   </div>   <div class="panel-body">     <ng-content select="my-panel-content"></ng-content>   </div> </div>   then you can query for it like
@ViewChild('panelHeading') panelHeading;   and set a property depending on whether there are children or not
constructor(private cdRef:ChangeDetectorRef) {}  showHeading:boolean = false;  ngAfterViewInit() {   this.showHeading = this.panelHeading.nativeElement && this.panelHeading.nativeElement.children.length > 0;   this.cdRef.detectChanges(); }   If <my-panel-heading> is an Angular2 component, then you can also use
@ContentChild(MyPanelHeading) panelHeading:MyPanelHeading;  constructor(private cdRef:ChangeDetectorRef) {}  showHeading:boolean = false;  ngAfterViewInit() {   this.showHeading = this.panelHeading != null;   this.cdRef.detectChanges(); } 
                        You'd have to remove all your spaces but you could do this with CSS if you really cared about it (ng-content doesn't take up space):
.panel-heading:empty { display: none }  <div class="panel-heading"><ng-content select="my-panel-heading"></ng-content></div> 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With