Detect if a transclude content has been given for a angularjs directive
Solution 1
After release of Angular v1.5 with multi-slot transclusion it's even simpler. For example you have used component
instead of directive
and don't have access to link
or compile
functions. Yet you have access to $transclude
service. So you can check presence of content with 'official' method:
app.component('myTransclude', {
transclude: {
'slot': '?transcludeSlot'
},
controller: function ($transclude) {
this.transcludePresent = function() {
return $transclude.isSlotFilled('slot');
};
}
})
with template like this:
<div class="progress" ng-class="{'with-label': withLabel}">
<div class="label"><span ng-transclude="slot"></span>
<div class="other">...</div>
</div>
Solution 2
Based on @Ilan's solution, you can use this simple $transclude function to know if there is transcluded content or not.
$transclude(function(clone){
if(clone.length){
scope.hasTranscluded = true;
}
});
Plnkr demonstrating this approach with ng-if to set default content if nothing to transclude: http://plnkr.co/hHr0aoSktqZYKoiFMzE6
Solution 3
Here is a plunker: http://plnkr.co/edit/ednJwiceWD5vS0orewKW?p=preview
You can find the transcluded element inside the linking function and check it's contents:
Directive:
app.directive('progressbar', function(){
return {
scope: {},
transclude: true,
templateUrl: "progressbar.html",
link: function(scope,elm){
var transcluded = elm.find('span').contents();
scope.withLabel = transcluded.length > 0; // true or false
}
}
})
Template:
<div class="progress" ng-class="{'with-label': withLabel}">
<div class="label"><span ng-transclude></span>
<div class="other">...</div>
</div>
You can also create your custom transclusion directive like so:
app.directive('myTransclude', function(){
return {
link: function(scope, elm, attrs, ctrl, $transclude){
$transclude(function(clone){
// Do something with this:
// if(clone.length > 0) ...
elm.empty();
elm.append(clone);
})
}
}
})
Related videos on Youtube
![Sebastian](https://i.stack.imgur.com/b25g2.jpg?s=256&g=1)
Sebastian
Software Developer with focus on mobile & web applications, highly addicted to test & behaviour driven development, passionate about intelligent software systems. Interested in new technologies, web applications, SaaS and PaaS solutions. Strong background in Ruby on Rails, HTML5, Phonegap/Cordova, Javascript, Heroku. Some experience on Java (plain and for Android), ObjectiveC, C#.
Updated on June 06, 2022Comments
-
Sebastian about 2 years
I have a directive (a progressbar) which should have two possible states, one without any description and one with a label on the left side. It would be cool to simple use the transcluded content for this label.
Does anyone know how I can add a class to my directive depending whether a transclude content has been given or not?
So I want to add:
<div class="progress" ng-class="{withLabel: *CODE GOES HERE*}"> <div class="label"><span ng-transclude></span> <div class="other">...</div> </div>
Thanks a lot!
-
Sebastian over 10 yearsThanks thats awesome!
-
John Ding about 10 yearsllan, you have some code commented out, in what case can this be true? clone.length > 0, I tested, it is always 1
-
plong0 almost 9 yearsyou would have !clone.length if there is nothing to transclude (ie empty <progressbar></progressbar>)
-
pilau almost 8 yearsExactly what I was looking for!
-
Robba over 7 yearsThis works well when using the multi-slot feature. But what if I just use the
transclude: true
setting on the component and want to know if any content is provided? -
Snook almost 7 yearsShouldn't ng-class be:
ng-class="{'with-label': transcludePresent}"
? -
Paul Carlton over 5 yearsThis looks like the most straight forward and quickest way in a component. Within the component controller, inject
$transclude
and then use this function when it runs before$onInit()
is called.