我在拼命寻找同一问题的答案时发现了这个问题,虽然Eric 的回答为我指明了正确的方向,但它并没有按预期工作*。
在玩了几天 ngRow 和 ngAggregate 对象的内容之后,这就是我最后得出的结论。
我的 aggregateTemplate 与 Eric 的非常相似,但有一些不同之处。首先,我在 ( span class="{{row.aggClass()}}></span>"
) 中添加了展开/折叠图标。我还将 移至ng-click="expandGroupChildren($event, row)"
包含div
,并添加ng-click="$event.stopPropagation()"
到复选框中。这意味着单击除复选框之外的任何位置将展开/折叠组。最后,我重命名了一些函数。
var aggregateTemplate = '<div ng-init="initAggregateGroup(row)" ng-style="rowStyle(row)" style="top: 0; height: 48px; left: 0; cursor:pointer" class="ngAggregate" ng-click="expandGroupChildren($event, row)">' +
'<span class="{{row.aggClass()}}"></span>' +
'<input class="ngSelectionHeader" type="checkbox" ng-show="multiSelect" ng-checked="row.status.isChecked" ng-model="row.status.isChecked" ng-change="setGroupSelection(row)" ng-click="$event.stopPropagation()" />' +
'<span class="ngAggregateText">{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span>' +
'</div>';
但是功能代码是我真正分歧的地方。
首先,这对我不起作用:
$scope.gridOptions.selectItem(entry.rowIndex, group.status.isChecked)
相反,在这个版本中,我们称之为:
row.selectionProvider.setSelection (row, group.status.isChecked)
由于它采用行本身而不是索引,因此无论索引可能变得多么纠结,它都能正常工作。
此版本也适用于嵌套组。例如,当您按City > Age分组时,您会得到一个包含组53的组Minnesota,单击组标题53将选择居住在 Minesota 的所有 53 岁的人,但不会选择 53 岁的人在其他城市或其他年龄的明尼苏达州。另一方面,单击 Minnesota 的组标题将选择 Minnesota 中的每个人,以及每个子组的组标题复选框。同样,如果我们在Minnesota组中只有53 岁的人,那么单击53复选框也会勾选Minnesota复选框。
这让我想到了最后的改变。每个组有一个观察者(我通常不喜欢观察者并试图避免它们,但有时它们是必要的邪恶),我们跟踪每个组内的选择,并在每行时自动勾选组标题中的框被选中。就像网格顶部的全选复选框一样。
所以这里是代码:
angular.extend ($scope, {
initAggregateGroup : initAggregateGroup,
expandGroupChildren : expandGroupChildren,
setGroupSelection : setGroupSelection
});
function initAggregateGroup (group) {
group.status = {
isChecked: getGroupSelection (group)
};
$scope.$watch (
function () {
return getGroupSelection (group)
},
function (isSelected) {
setGroupSelection (group, isSelected);
}
)
}
function expandGroupChildren ($event, group) {
$event.stopPropagation ();
$event.preventDefault ();
group.toggleExpand ();
}
function setGroupSelection (group, isSelected) {
// Sets the field when called by the watcher (in which case the field needs to be updated)
// or during recursion (in which case the objects inside aggChildren don't have it set at all)
if (_.isBoolean (isSelected)) {
group.status = { isChecked : isSelected }
}
// Protects against infinite digest loops caused by the watcher above
if (group.status.isChecked === getGroupSelection (group)) { return }
_.forEach (group.children, function (row) {
// children: ngRow objects that represent actual data rows
row.selectionProvider.setSelection (row, group.status.isChecked);
});
_.forEach (group.aggChildren, function (subGroup) {
// aggChildren: ngAggregate objects that represent groups
setGroupSelection (subGroup, group.status.isChecked);
});
}
function getGroupSelection (group) {
if (group.children.length > 0) {
return _.every (group.children, 'selected');
}
if (group.aggChildren.length > 0) {
return _.every (group.aggChildren, getGroupSelection);
}
return false;
}
*单击 aggregateTemplate 中的复选框将从整个网格中选择看似随机的行集合(看似随机,因为它在不同的会话中是一致的,对于相同的数据)。
我认为问题(至少在 ngGrid 2.0.12 中对我来说)是 ngGrid 没有正确地将 rowIndex 字段映射到其模型中的正确行。我认为这是因为为分组和排序重新排列了行,并且内部映射没有跟上。