angulartransclusion

How to check whether ng-content exists


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>


Solution

  • 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();
    }