angularangular-templatetransclusion

Angular: wrap transcluded content if it exists


How can I wrap transcluded content, only if it exists?

For example, template of my-component:

<div>
    ...
    <div *ngIf="isInvalid" class="error">
        <h2>Extra errors:</h2>
        <ng-content select="extra-error-messages"></ng-content>
    </div>
    ...
</div>

The component could be used so

<my-component>
    <extra-error-messages>
       Do not ever try this!
    </extra-error-messages>
</my-component>

In this case div.error should be shown, or it could be used so

<my-component></my-component>

In this case div.error should not appear even if isInvalid is true.


Solution

  • You can get hold of extra-error-messages component through @ContentChild and check whether it is presented in parent template.

    So this should work in your case:

    @Component({
      selector: 'my-component',
      template: `
        <div>
            <h2>My component</h2>
            <div *ngIf="isInvalid && errorMessage" class="error">
                                     ^^^^^^^^^^^
                             check whether extra-error-messages is presented
                <h2>Extra errors:</h2>
                <ng-content select="extra-error-messages"></ng-content>
            </div>
        </div>
    
      `,
      styleUrls: ['./app.component.css']
    })
    export class MyComponent  {
      isInvalid = true;
    
      @ContentChild(ErrorMessagesComponent) errorMessage; // get transcluded component
    }
    

    Stackblitz Example

    For more complex scenario see: