Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular ui-grid selecting all under grouping

https://jsfiddle.net/4byyuqtc/1/

enter image description here

I'm looking to have the ui-grid select all "children" under a grouping when the grouping line is selected. In this case Kit Kat(1), Mr. Goodbar(1), Krackel(2) and ultimately selecting the actual records (the non bold lines). One would expect that when selecting a parent in a grouping all it's children would get selected as well.

Currently when selecting the 1 grouping above the actual records in the data (the non bold lines) it does select those actual records with the following code:

$scope.gridApi.selection.on.rowSelectionChanged($scope, function (rowChanged) {
    console.log(rowChanged.treeLevel);
    if (typeof (rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
        // this is a group header
        children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
        console.log(children);
        children.forEach(function (child) {
            if (rowChanged.isSelected) {
                $scope.gridApi.selection.selectRow(child.entity);
            } else {
                $scope.gridApi.selection.unSelectRow(child.entity);
            }
        });
    }
});

I'm not experienced enough with ui-grid at this point to figure out how to cycle through children of the selected line and select all of them.

[EDIT]

With Paul's code below it doesn't select the groupings but it's closer. This screenshot is me selecting the first 337 record. Notice it selects that record and all the lowest child records (which is good because ultimately those are the ones that matter) but visually the grouped records (MFG and Item Desc group) aren't selected and need to be as the user won't ever open the lowest data records so they need to see the groups selected.

enter image description here

like image 214
user441521 Avatar asked Jul 10 '17 18:07

user441521


2 Answers

I checked the documentation and I don't think there's any exposed API Method. You could recursively select/deselect rows as a solution. Please try out the example below.

$scope.gridApi.selection.on.rowSelectionChanged($scope, function (rowChanged) {
                    console.log(rowChanged.treeLevel);
                    if (typeof(rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
                        var children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
                        selectChildren(children, rowChanged.isSelected);
                    }
                });

function selectChildren(gridRows, selected) {
                        if (gridRows && gridRows.length > 0) {
                            gridRows.forEach(function (child) {
                                if (selected) {
                                    $scope.gridApi.selection.selectRow(child.entity);
                                } else {
                                    $scope.gridApi.selection.unSelectRow(child.entity);
                                }

                                var children = $scope.gridApi.treeBase.getRowChildren(child);
                                selectChildren(children, selected); //recursively select/de-select children
                            });
                        }
                    }

Here's a working Plunkr: http://plnkr.co/edit/XsoEUncuigj9Cad1vP5E?p=preview

Handling automatic deselection is a bit more tricky though as it seems the api doesn't handle that really well.

UPDATE

So I checked the jsFiddle you shared and managed to get it working with a slight tweak.

I modified the selectionHandler to the following:

onRegisterApi: function(gridApi) {
  $scope.gridApi = gridApi;
  $scope.gridApi.selection.on.rowSelectionChanged($scope, function(rowChanged) {
    if (rowChanged.treeNode.parentRow) { //Added this parent row selection
        rowChanged.treeNode.parentRow.setSelected(rowChanged.isSelected);
    }
    console.log(rowChanged.treeLevel);
    if (typeof(rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
      var children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
      selectChildren(children, rowChanged.isSelected);
    }
  });

Please see this fork of your code: https://jsfiddle.net/1eg5v77w/

The downside with this is that if you select a low level entry (one without children) it will still select its parent. If you really really want this to work as well, you'll have to access the DOM and make some ugly checks.

$scope.gridApi.selection.on.rowSelectionChanged($scope, function(rowChanged, $event) {
        var wasHeaderRowClicked = true;
        try {   //This can be written more beautifully if you used jQuery. But I would still be against it as it relies on the class of the ui-grid never changing when you update your ui-grid version.
          wasHeaderRowClicked = $event
          .srcElement
          .parentElement
          .parentElement
          .parentElement
          .previousElementSibling
          .firstChild
          .firstChild
          .firstChild
          .getAttribute('class') === 'ui-grid-icon-minus-squared';
        } catch(err) { console.log('Couldnt determine if header row was clicked'); }
        if (rowChanged.treeNode.parentRow && wasHeaderRowClicked) {
            rowChanged.treeNode.parentRow.setSelected(rowChanged.isSelected);
        }
        console.log(rowChanged.treeLevel);
        if (typeof(rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
          var children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
          selectChildren(children, rowChanged.isSelected);
        }
      });

Here is the fiddle: https://jsfiddle.net/Lf8p7Luk/1/

I'd also like to add, thanks to this post, that according to the UI-Grid documentation: Group header rows cannot be edited, and if using the selection feature, cannot be selected. They can, however, be exported.

So it is intentional that it's so difficult to get this to work because it's not the intended design. My recommendation would be to alter your logic to either use Tree Levels or get around the selection logic because even though my fork is currently selecting everything, you will most likely run into other issues down the road. For example: I couldn't get automatic deselection to work in the grid when you click on another group header.

like image 76
Sal Avatar answered Jan 07 '23 06:01

Sal


If you still have the issue take a look with this..

https://github.com/angular-ui/ui-grid/issues/3911

like image 26
Deepak Avatar answered Jan 07 '23 07:01

Deepak