1
votes

I have an ng-grid with 6 columns in it, and as a default set up each column is 100px, so the grid itself is 600px. The columns are resizable but I want to keep the overall grid width the same, to ensure that there are no horizontal scroll bars. So, for example, if I change the second columns width to 150px I would want the overall width to stay at 600px (so maybe an adjacent cell will change size to 50px) - this way I don't get a scroll bar.

Does anybody know if there is a plugin that can do this/help me accomplish this?

I've included a plunker: http://plnkr.co/edit/4LRHQPg7w2eDMBafvy6b?p=preview

In this example, I would want to keep the table width at 600px, so if I expand "Field 2" you will see "Field 4" go off the edge of the viewable area for the grid and a horizontal scroll bar appear. The behaviour I want is for a different column (probably the adjacent column - "Field 3") to shrink in size automatically, so that the grid stays at 600px and the horizontal scroll bar doesn't appear.

2
Any chance you can Plunker this?user1135469

2 Answers

1
votes

After a lot of time searching the web for an answer, I started with Paul Witherspoon idea of watching the isColumnResizing property and after reading about ng-grid plugins I came up with this plugin solution:

Plunker: http://plnkr.co/edit/Aoyt73oYydIB3JmnYi9O?p=preview

Plugin code:

function anchorLastColumn () {
    var self = this;
    self.grid = null;
    self.scope = null;
    self.services = null;
    self.init = function (scope, grid, services) {
      self.grid = grid;
      self.scope = scope;
      self.services = services;

      self.scope.$watch('isColumnResizing', function (newValue, oldValue) {
        if (newValue === false && oldValue === true) { //on stop resizing
          var gridWidth = self.grid.rootDim.outerWidth;
          var viewportH = self.scope.viewportDimHeight();
          var maxHeight = self.grid.maxCanvasHt;
          if(maxHeight > viewportH) { // remove vertical scrollbar width
              gridWidth -= self.services.DomUtilityService.ScrollW;
          }

          var cols = self.scope.columns;
          var col = null, i = cols.length;
          while(col == null && i-- > 0) {
              if(cols[i].visible) {
                  col = cols[i]; // last column VISIBLE
              }
          }
          var sum = 0;
          for(var i = 0; i < cols.length - 1; i++) {
                if(cols[i].visible) {
                    sum += cols[i].width;
                }
          }

          if(sum + col.minWidth <= gridWidth) {
            col.width = gridWidth - sum; // the last gets the remaining
          }
        }
      });
    }
}

and in the controller

$scope.gridOptions = { 
  data: 'myData',
  enableColumnResize: true,
  plugins: [new anchorLastColumn()],
  columnDefs: $scope.columnDefs 
};

It is not a perfect solution but works for me and I hope that it will help others.

0
votes

I found a way to do this using a watch on the isColumnResizing property:

    $scope.$watch('gridOptions.$gridScope.isColumnResizing', function (newValue, oldValue) {

        if (newValue === false && oldValue === true) { //on stop resizing
            $scope.ColResizeHandler($scope.gridOptions.$gridScope.columns);
        }
    }, true);

then I was able to resize the columns in the resize handler I created:

    $scope.ColResizeHandler = function (columns) {
        var origWidth;
        var col1 = undefined;
        var col2 = undefined;
        var widthcol2;
        var found = false;
        var widthDiff = 0;
        angular.forEach(columns, function (value) {
            if (col2 == undefined && value.visible) {
                if (found) {
                    origWidth += value.width;
                    col2 = value;
                    colSizeLimits(col2, widthDiff);
                    found = false;
                }
                if (value.origWidth != undefined && value.origWidth != value.width && col2 == undefined) {
                    found = true;
                    col1 = value;
                    widthDiff = value.width - value.origWidth;
                    origWidth = value.origWidth;
                }
            }
        });

        if (col2 == undefined) {
            //this was the last visible column - don't allow resizing
            col1.width = origWidth;
        }
        else {
            //ensure limits haven't been blown to cope with reizing
            if (col1.width + col2.width != origWidth) {
                var diff = (col1.width + col2.width) - origWidth;
                colSizeLimits(col1, diff);
            }
        }

        col1.origWidth = col1.width;
        col2.origWidth = col2.width;

    }

There are 2 issues with this.

1 - if you resize and drag the column sizer outside of the grid (i.e. all the way over and out of the ng-grid viewable area) the isColumnResizing watch doesn't execute when you stop dragging and release the resizer. (I think this may be a bug in ng-grid because it does actually resize the column to where you have dragged the resizer, even if it is outside the grids viewable area, it just doesn't fire the watch code).

2 - if you avoid this issue and just drag within the viewable grid area then the columns will resize but only after you finish dragging the resizer, so the ui looks a little funny (i.e. if I expand a column then the adjacent column will not shrink until I click off the resizer and stop dragging).

I'll be working on these issues and will post any updates/fixes I find.