-->

How to dynamically adjust height in Angular ui-gri

2019-08-25 03:25发布

问题:

I was looking at the following example of treeview using Angular 1.5: link

In the css section it specifies a fixed height for .grid as follows:

.grid {
  width: 500px;
  height: 500px;
}

Is there a way of dynamically adjusting this height according to how a tree node is clicked to expand?

The relevant documentation for treeview is here. However, the example shown there also has a fixed height, which I would like to change to dynamic height.

回答1:

I managed to find a solution by implementing methods that dynamically change the container height. In the controller, I first initalize variables that will be used later in JS and the template using ng-style:

//===================================================
// Initalize height that will be altered later based 
// on tree expand/collapse events
//===================================================
var row_height = 30; // use this to set height everywhere
$scope.height = row_height;
$scope.height_px = row_height + 'px'; // used in template with ng-style 

Then while initialize the tree view grid options, one can reference row_height. We also add the logic to add or deduct height based on rowExpanded and rowCollapsed events in the options:

$scope.gridOptions = {
    rowHeight: row_height,
    enableSorting: true,
    enableFiltering: false,
    //.....continue other options.....
    onRegisterApi: function(gridApi) {
        $scope.gridApi = gridApi;

        // Add container height for row expanded
        $scope.gridApi.treeBase.on.rowExpanded(null, function(row) {
            addHeight(row.treeNode.children.length);
        });

        // Deduct container height for row collapsed after considering 
        // all child node expanded state
        $scope.gridApi.treeBase.on.rowCollapsed(null, function(row) {
            // get number of children that are already expanded
            var count =  row.treeNode.children.length;
            for(var i=0; i <  row.treeNode.children.length; i++) {
                count += getChildCount( row.treeNode.children[i]);
            }
            deductHeight(count);
        });
    }
}

We then add the methods to controller that are needed for addHeight(), deductHeight() and getChildCount() to work:

// Method to add height of container dynamically based on number of rows
var addHeight = function (num_rows) {
    $scope.height += num_rows * row_height;
    $scope.height_px = $scope.height + 'px';            
};

// Method to deduct height of container dynamically based on number of rows
var deductHeight = function (num_rows) {
    $scope.height -= num_rows * row_height;
    if($scope.height <= 0) {
        $scope.height = row_height;
    }
    $scope.height_px = $scope.height + 'px';            
};

// Method to get count of expanded child rows for a given node (used recursively)
var getChildCount = function (node) {
    var count = 0;
    if(node.state == 'expanded') {
        // change the state to collapsed for all child nodes
        node.state = 'collapsed';
        count += node.children.length;                
        for(var i=0; i < node.children.length; i++) {
            count += getChildCount(node.children[i]);
        }
        return count;
    } else {
        return 0;
    }
};

Notice that we recursively get node count when we collapse a node. We also change the state of sub-nodes to collapsed so that the height is calculated correctly the next time.

Finally in the template, we need to reference the $scope.height_px which gives the dynamic height for the container. We do this by setting ng-style="{ 'height': height_px }" as follows:

<div id="gridTree-1" ui-grid="gridOptions" class="grid" ui-grid-tree-view ui-grid-auto-resize ng-style="{ 'height': height_px }"></div>

One problem that I encountered after this was that the mouse scroll stopped working when it was placed on top of the grid. This problem apparently has a solution as suggested here. However, the actual problem relates to disablement of scroll functionality in ui-grid.js. In version 3.1.1 line 2721 reads event.preventDefault();. I had to comment this line out for the scroll to work normally again.



回答2:

To set Manual Height for UI-Grid Tree View when user Expand or Collapse the parent row

checkout onRegisterApi:

var rowtpl = '<div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell"  ng-class="{ \'disabled\': true, \'ui-grid-row-header-cell\': col.isRowHeader }" ui-grid-cell></div>';
$scope.gridOptions = {
    enableColumnResizing: true,
    enableSorting: false,
    enableColumnMenus: false,
    showTreeExpandNoChildren: false,
    enableExpandAll:false,
    enableTreeView: true,
    rowTemplate: rowtpl,
    enableFiltering: true,
    enableRowSelection: true,
    enableRowHeaderSelection: false,
    enableHorizontalScrollbar: 0,
    multiSelect: false,
    modifierKeysToMultiSelect: false,
    noUnselect: true,
    onRegisterApi: function (gridApi) {

        $scope.gridApi = gridApi;
     //Row Collapse Set Height 
        $scope.gridApi.treeBase.on.rowCollapsed($scope, function (row) {

            gridHeight();

        });
      //Row Expand Set Height 
     $scope.gridApi.treeBase.on.rowExpanded($scope, function (row) {

            gridHeight();

        });}}

Now look at function gridHeight() where you can easily set value for height

function gridHeight() {
    //timeout function is used due to late updation of $scope.gridApi.core.getVisibleRows()
    $timeout(function () {
        // 40: header height
        // 30: height for each row


        const visibleRowHeight = 40 + (30 * $scope.gridApi.core.getVisibleRows().length);
        if (visibleRowHeight > 280) {
            vm.totalHeight = 280;
        }

        else {
            vm.totalHeight = visibleRowHeight;
        }
        //Adjust your height max and min accordingly like i did

    }, 200);  
}

View:

<div id="grid" ui-grid="gridOptions" class="grid" ui-grid-tree-view ui-grid-tree-row-header-buttons ui-grid-cellNav ui-grid-auto-resize ui-grid-resize-columns ui-grid-selection ng-style="{height: vm.totalHeight+'px'}"></div>