[英]AngularJS: Hide parent based on number of hidden children
I have the following code: 我有以下代码:
<div ng-hide="items.length == 0">
<li ng-repeat="item in items" ng-hide="item.hide == true">
{{ item.name }} <hide-button />
</li>
</div>
Imagine that I have 10 items. 想象一下我有10件物品。 When I click the button, I set the item.hide to true and the item disappear.
单击按钮时,将item.hide设置为true,该项目消失。 When I hide all 10 items, I want to hide the main div.
当我隐藏所有10个项目时,我想隐藏主div。 What's the best way to achieve this with AngularJS?
用AngularJS实现此目标的最佳方法是什么?
An approach might be to use a function like this: 一种方法可能是使用如下函数:
$scope.checkItems = function () {
var total = $scope.items.length;
for (var i = 0; i < $scope.items.length; ++i) {
if ($scope.items[i].hide) total--;
}
return total === 0;
};
and change the ngHide attribute on the outer div: 并更改外部div上的ngHide属性:
ng-hide="checkItems()"
jsfiddle : http://jsfiddle.net/u6vkf6bt/ jsfiddle : http : //jsfiddle.net/u6vkf6bt/
Another approach is to declare a $scope.allHidden
variable and watch over the array like this: 另一种方法是声明
$scope.allHidden
变量,并像这样监视数组:
$scope.$watch('items', function (newItems) {
var all = true;
for (var i = 0; i < newItems.length; ++i) {
if (newItems[i].hide !== true) all = false;
}
$scope.allHidden = all;
}, true);
This is checking when anything inside the array is changed, and check if all the hide attributes are set to true. 这是检查何时更改数组内部的任何内容,并检查是否所有hide属性都设置为true。
Then set it on the ngHide attribute: 然后在ngHide属性上进行设置:
ng-hide="allHidden"
jsfiddle : http://jsfiddle.net/u6vkf6bt/1/ jsfiddle : http : //jsfiddle.net/u6vkf6bt/1/
Among the two, I would choose the first approach, because deep watching may cause performance issues: 在这两种方法中,我会选择第一种方法,因为深度监视可能会导致性能问题:
This therefore means that watching complex objects will have adverse memory and performance implications.
因此,这意味着观看复杂的对象将对内存和性能产生不利影响。
From here , under $watch(watchExpression, listener, [objectEquality]);
从这里
$watch(watchExpression, listener, [objectEquality]);
when objectEquality
is set to true. 当
objectEquality
设置为true时。
Yet another approach would be updating the counter of hidden items whenever a single item is hidden. 另一种方法是每当隐藏单个项目时更新隐藏项目的计数器。 Of course this would require the hiding code to be placed within your controller, like this:
当然,这需要将隐藏代码放置在您的控制器中,如下所示:
$scope.allHidden = false;
// if items can have hide = true property set already from the start
var hiddenItems = $scope.items.filter(function (item) {
return item.hide;
}).length;
// or if they are all initially visible, a straightforward approach:
// var hiddenItems = 0;
$scope.hideItem = function (item) {
item.hide = true;
hiddenItems++;
if (hiddenItems === $scope.items.length) {
$scope.allHidden = true;
}
}
and the hiding would need to be done like this: 并且隐藏将需要像这样完成:
<li ng-repeat="item in items" ng-hide="item.hide == true">{{ item.name }}
<button ng-click="hideItem(item)">hide</button>
</li>
jsfiddle : https://jsfiddle.net/723kmyou/1/ jsfiddle : https : //jsfiddle.net/723kmyou/1/
Pros for this approach 这种方法的优点
Cons for this approach 这种方法的缺点
A couple of reasons why I didn't like the other solutions: 我不喜欢其他解决方案的几个原因:
My preferred solution is to actually look for the first visible item: http://plnkr.co/edit/FJv0aRyLrngXJWNw7nJC?p=preview 我的首选解决方案是实际查找第一个可见项目: http : //plnkr.co/edit/FJv0aRyLrngXJWNw7nJC?p=preview
angular.module('MyApp',[]);
angular.module('MyApp').directive('myParent', function(){
return {
restrict: 'A',
link:function(scope, element){
scope.$watch(function(){
return element.find('>:visible:first').length > 0;
}, function( visible ){
if ( visible ){
element.show();
}else{
element.hide();
}
})
}
}
});
<div my-parent>
<div class="hidden">one child</div>
<div class="hidden">another child</div>
</div>
<div my-parent>
<div class="hidden">third child</div>
<div>another child</div>
</div>
You can even expand this by passing a selector to 'my-parent' attribute to be used in the directive. 您甚至可以通过将选择器传递给指令中要使用的'my-parent'属性来扩展它。 allows to better specify which items to look for.
可以更好地指定要查找的项目。
I like this approach as it has almost no assumptions. 我喜欢这种方法,因为它几乎没有任何假设。 This can be used for any scenario where children might be hidden.
这可用于可能隐藏孩子的任何情况。 not necessarily
ng-repeat
. 不一定是
ng-repeat
。 However the watch might be costly as we're using a :visible
selector. 但是,由于我们使用
:visible
选择器,因此手表可能会很昂贵。
another - assuming ng-repeat is involved - is to watch the value on the scope - http://plnkr.co/edit/ZPVm787tWwx9nbJTNg1A?p=preview 另一个-假设涉及ng-repeat-是观察示波器上的值-http: //plnkr.co/edit/ZPVm787tWwx9nbJTNg1A?p=preview
app.directive('myParent', function(){
return{
restrict: 'A',
link: function(scope, element,attrs){
scope.$watch(function(){
try{
value = scope.$eval(attrs.myParent);
var i = value.length-1;
for ( ; i >= 0; i-- ){
if ( value[i].hide != false ){
return true;
}
}
}catch(e){
return false
}
return false;
}, function( newValue ){
if ( !!newValue ) { element.show(); } else { element.hide();}
})
}
}});
<ul my-parent="awesomeThings">
<li ng-repeat="thing in awesomeThings">{{thing.value}}</li>
</ul>
The watch here might be less costly, not sure, but it doesn't handle the dom, so there's a good chance for that.. 这块手表的价格可能不太便宜(不确定),但它不能处理dom,因此有很大的机会。
While this is very similar to other solutions, it is implemented as a highly reusable directive, and looks for the first visible item. 尽管这与其他解决方案非常相似,但它是作为高度可重用的指令实现的,并寻找第一个可见项。
In my solutions I also assume jquery is available. 在我的解决方案中,我还假设可以使用jquery。 There are many other ways to implement this if required: AngularJS: element.show() in directive not working
如果需要,还有许多其他方法可以实现此目的: AngularJS:指令中的element.show()不起作用
regarding watch
performance, not sure which way is better. 关于
watch
性能,不确定哪种方法更好。 I am using a function to evaluate the watched value and I am not sure if this is the best way to handle it. 我正在使用一个函数来评估监视的值,并且不确定这是否是处理它的最佳方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.