3

是否可以在 ng-grid 分组标题中有一个复选框?单击该分组复选框时,应选中该特定组下的行的所有复选框。其他组行应保持未选中状态。

现在,当我有如下的 gridOptions 时,我看到所有行的复选框,并且在表头中。当拖动列标题以将其用于分组时,分组的行标题没有复选框。有人可以帮忙吗?

$scope.gridOptions = {
    data: 'myData',
    showGroupPanel: true,
    showSelectionCheckbox: true,
    jqueryUITheme: true,
    enableCellSelection: true,
    enableRowSelection: true,
    enableCellEdit: false,
    pinSelectionCheckbox: false,
    selectWithCheckboxOnly: true
};
4

2 回答 2

2

为了做到这一点,您必须首先覆盖默认的 aggregateTemplate :

$scope.gridOptions = {
  data: 'myData',
  showGroupPanel: true,
  showSelectionCheckbox: true,
  jqueryUITheme: true,
  enableRowSelection: true,
  aggregateTemplate: "<div ng-init=\"initAggregateGroup(row)\" ng-style=\"rowStyle(row)\" style=\"top: 0px; height: 48px; left: 0px; cursor:pointer\" class=\"ngAggregate\">" +
"    <span class=\"ngAggregateText\" ng-click=\"expandGroupChilds($event, row)\">{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span>" +
"<input class=\"ngSelectionHeader\" type=\"checkbox\" ng-show=\"multiSelect\" ng-checked=\"row.status.isChecked\" ng-model=\"row.status.isChecked\" ng-change=\"toggleGroupSelectedChilds(row)\" /></div>"  
};

然后您可以在控制器中添加这些功能:

$scope.expandAll = function($event){
   $scope.isAllCollapsed = !$scope.isAllCollapsed;
   _.each($scope.ngGridOptions.ngGrid.rowFactory.aggCache, function(row){
     row.toggleExpand();
   });
};

$scope.initAggregateGroup = function(group){
   group.status = {
      isChecked: false
   };
};

$scope.toggleGroupSelectedChilds = function(group){
  _.each(group.children, function(entry){
      $scope.ngGridOptions.selectItem(entry.rowIndex, group.status.isChecked);
  });
};

$scope.expandGroupChilds = function($event, group){
   $event.stopPropagation();
   $event.preventDefault();

   group.toggleExpand();
};
于 2016-02-19T09:01:28.833 回答
2

我在拼命寻找同一问题的答案时发现了这个问题,虽然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 字段映射到其模型中的正确行。我认为这是因为为分组和排序重新排列了行,并且内部映射没有跟上。

于 2016-04-25T15:19:52.950 回答