Robert Robert - 3 months ago 16
AngularJS Question

How to not render transclusion slot when it's not provided in AngularJS?

I have an AngularJS component which uses transclusion with 2 transclusion slots. One of them (

messageHeading
) is optional and sometimes will not be provided at all. Code below:

message.js



import template from "./messsage.html";

angular.component('message', {
transclude: {
heading: '?messageHeading',
content: 'messageContent'
},
template
});


message.html



<aside class="message">
<h2 class="message__heading"
ng-transclude="heading"></h2>
<p class="message__paragraph"
ng-transclude="content"></p>
</aside>


Question



How can I not render
<h2>
element at all, when
messageHeading
is not provided?
In the current default behaviour it's rendered, only with empty contents, but I want it to never appear in the DOM.

Using
ngIf
on
<h2>
seems like a natural way to do it, but I don't know how to write a condition which would be true only when the transclusion argument was provided.

Answer Source

I worked it out myself. There is $transclude service, which provides method isSlotFilled(nameOfTheSlot) to check if the slot has been filled. You can use that as a value of the ngIf condition and so render <h2> only when the slot has been filled.

message.js

import template from "./messsage.html";


class MessageController {
    constructor($transclude) {
        this.hasHeading = $transclude.isSlotFilled('heading');
    }
}


angular.component('message', {
    transclude: {
        heading: '?messageHeading',
        content: 'messageContent'
    },
    controller: MessageController,
    template
});

message.html

<aside class="message">
    <h2 class="message__heading"
        ng-if="$ctrl.hasHeading"
        ng-transclude="heading"></h2>
    <p class="message__paragraph"
       ng-transclude="content"></p>
</aside>