如果嵌入的内容为空,如何隐藏元素?
Posted
技术标签:
【中文标题】如果嵌入的内容为空,如何隐藏元素?【英文标题】:How to hide element if transcluded contents are empty? 【发布时间】:2013-03-24 00:10:45 【问题描述】:我创建了一个显示键/值对的非常简单的指令。如果嵌入的内容为空(零长度或只是空格),我希望能够自动隐藏元素。
我不知道如何访问从指令中嵌入的内容。
app.directive('pair', function($compile)
return
replace: true,
restrict: 'E',
scope:
label: '@'
,
transclude: true,
template: "<div><span>label</span><span ng-transclude></span></div>"
);
例如,我想显示以下元素。
<pair label="My Label">Hi there</pair>
但是接下来的两个元素应该被隐藏,因为它们不包含任何文本内容。
<pair label="My Label"></pair>
<pair label="My Label"><i></i></pair>
我是 Angular 的新手,所以可能有一种开箱即用的好方法来处理这类事情。任何帮助表示赞赏。
【问题讨论】:
【参考方案1】:可能有点晚了,但您也可以考虑使用 CSS 伪类 :empty。 所以,这会工作(IE9+)
.trancluded-item:empty
display: none;
该元素仍将在 dom 中注册,但将为空且不可见。
【讨论】:
这非常优雅,也适用于非 angularjs 应用程序。【参考方案2】:如果你不想每次都使用 ng-show,你可以创建一个指令来自动完成:
.directive('hideEmpty', ['$timeout', function($timeout)
return
restrict: 'A',
link:
post: function (scope, elem, attrs)
$timeout(function()
if (!elem.html().trim().length)
elem.hide();
);
;
]);
然后你可以将它应用到任何元素上。在您的情况下,它将是:
<span hide-empty>label</span>
【讨论】:
【参考方案3】:之前提供的答案很有帮助,但并没有完美地解决我的情况,所以我通过创建单独的指令想出了一个不同的解决方案。
创建一个基于属性的指令(即restrict: 'A'
),它只检查元素的所有子节点上是否有任何文本。
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);
如果你只想检查主要元素:
link: function (scope, element, attr)
if (!element.text().trim().length)
element.attr('style', 'display: none;');
为了解决我的问题,我只需要检查是否有任何子节点:
link: function (scope, element, attr)
if (!element.children().length)
element.attr('style', 'display: none;');
YMMV
【讨论】:
【参考方案4】:我是这样做的,使用 controllerAs。
/* 指令内部 */
controllerAs: "my",
controller: function ($scope, $element, $attrs, $transclude)
//whatever controller does
,
compile: function(elem, attrs, transcludeFn)
var self = this;
transcludeFn(elem, function(clone)
/* clone is element containing html that will be transcluded*/
var showTransclude = clone.text().trim().length ? true : false;
/* I set a property on my controller's prototype indicating whether or not to show the div that is ng-transclude in my template */
self.controller.prototype.showTransclude = showTransclude;
);
/* 模板内 */
<div ng-if="my.showTransclude" ng-transclude class="tilegroup-header-trans"></div>
【讨论】:
【参考方案5】:这是一种在模板上使用 ng-show
并在 compile transcludeFn
内检查转入的 html 是否具有文本长度的方法。
如果没有将文本长度ng-show
设置为隐藏
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;
);
);
Plunker demo
【讨论】:
+1 表示任何显示深奥 transcludeFn 用例的答案 :)。 在 transcludeFn 中,clone.text().trim().length
会更准确一些【参考方案6】:
我对 transclude 不是很熟悉,所以不确定它是否有帮助。
但在指令代码中检查空内容的一种方法是使用 iElement.text() 或 iElement.context 对象,然后将其隐藏。
【讨论】:
谢谢。我实际上尝试在link
函数中这样做,但到那时内容还没有被嵌入。以上是关于如果嵌入的内容为空,如何隐藏元素?的主要内容,如果未能解决你的问题,请参考以下文章