同じ問題に対する答えを必死に探しているときにこの質問を見つけました。エリックの答えは正しい方向を示していましたが、期待どおりに機能していませんでした*。
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を含むミネソタのグループを取得した場合、 53のグループ ヘッダーをクリックすると、ミネソタに住むすべての 53 歳が選択されますが、53 歳は選択されません。他の都市または他の年齢のミネソタ人。一方、ミネソタのグループ ヘッダーをクリックすると、ミネソタの全員が選択され、すべてのサブグループのグループ ヘッダー チェックボックスが選択されます。同様に、ミネソタグループに53 歳しかいない場合、 53チェックボックスをクリックすると、ミネソタチェックボックスもチェックされます。
そして、それが私を最終的な変化に導きます。グループごとのウォッチャーを使用すると (私は一般的にウォッチャーが好きではなく、それらを避けようとしますが、必要悪である場合もあります)、各グループ内の選択を追跡し、すべての行がグループ ヘッダーのボックスに自動的にチェックを入れます。が選択されます。グリッドの上部にあるすべて選択チェックボックスと同じです。
コードは次のとおりです。
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 フィールドをそのモデルの正しい行に適切にマッピングしていなかったことだと思います。これは、グループ化とソートのために行が再配置され、内部マッピングが追いついていなかったためだと思います。