How to hide element if transcluded contents are empty?
Here's an approach using ng-show
on the template and within compile transcludeFn
checking if transcluded html has text length.
If no text length ng-show
is set to hide
app.directive('pair', function($timeout) { return { replace: true, restrict: 'E', scope: { label: '@' }, transclude: true, template: "<div ng-show='1'><span>{{label}} </span><span ng-transclude></span></div>", compile: function(elem, attrs, transcludeFn) { transcludeFn(elem, function(clone) { /* clone is element containing html that will be transcludded*/ var show=clone.text().length?'1':'0' attrs.ngShow=show; }); } }});
Maybe a bit late but you can also consider using the CSS Pseudo class :empty.So, this will work (IE9+)
.trancluded-item:empty { display: none;}
The element will still be registered in the dom but will be empty and invisible.
The previously provided answers were helpful but didn't solve my situation perfectly, so I came up with a different solution by creating a separate directive.
Create an attribute-based directive (i.e. restrict: 'A'
) that simply checks to see if there is any text on all the element's child nodes.
function hideEmpty() { return { restrict: 'A', link: function (scope, element, attr) { let hasText = false; // Only checks 1 level deep; can be optimized element.children().forEach((child) => { hasText = hasText || !!child.text().trim().length; }); if (!hasText) { element.attr('style', 'display: none;'); } } }; }angular .module('directives.hideEmpty', []) .directive('hideEmpty', hideEmpty);
If you only want to check the main element:
link: function (scope, element, attr) { if (!element.text().trim().length) { element.attr('style', 'display: none;'); }}
To solve my problem, all I needed was to check if there were any child nodes:
link: function (scope, element, attr) { if (!element.children().length) { element.attr('style', 'display: none;'); }}
YMMV