15
votes

In AngularJS ui-grid , how can I configure the grid so that it can auto adjust the width of the columns according to the contents when it render?

I know there is a tutorial showing the auto size function, but that works only when you double click the column, I wish it could happen when the grid is initiated.

12
So where is the code from what you have tried?ajmajmajma

12 Answers

6
votes

use an asterisk in your column definition:

width:"*";
5
votes

There is a pluggin that do this: ui-grid-auto-fit-columns

GitHub: https://github.com/Den-dp/ui-grid-auto-fit-columns

Example: http://jsbin.com/tufazaw/edit?js,output

Usage:

<div ui-grid="gridOptions" ui-grid-auto-fit-columns></div>

angular.module('app', ['ui.grid', 'ui.grid.autoFitColumns'])
4
votes

I dont think this feature exists at this point. The uiGridColumnResizer directive is registering event listeners on dblclick, mousedown and mouseup. The dblclick event is basically going thru all the rendered cells and calculating the maximum width and setting it as the column width. This will be a performance issue if you have a lot of rows rendered.

I would probably just set a maximum possible width based on the data the grid will have.

Or try to replicate the behaviour in the uiGridColumnResizer.

 $elm.on('dblclick', function(event, args) {
      event.stopPropagation();

      var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

      // Don't resize if it's disabled on this column
      if (col.colDef.enableColumnResizing === false) {
        return;
      }

      // Go through the rendered rows and find out the max size for the data in this column
      var maxWidth = 0;
      var xDiff = 0;

      // Get the parent render container element
      var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');

      // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present
      var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');
      Array.prototype.forEach.call(cells, function (cell) {
          // Get the cell width
          // gridUtil.logDebug('width', gridUtil.elementWidth(cell));

          // Account for the menu button if it exists
          var menuButton;
          if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {
            menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');
          }

          gridUtil.fakeElement(cell, {}, function(newElm) {
            // Make the element float since it's a div and can expand to fill its container
            var e = angular.element(newElm);
            e.attr('style', 'float: left');

            var width = gridUtil.elementWidth(e);

            if (menuButton) {
              var menuButtonWidth = gridUtil.elementWidth(menuButton);
              width = width + menuButtonWidth;
            }

            if (width > maxWidth) {
              maxWidth = width;
              xDiff = maxWidth - width;
            }
          });
        });

      // check we're not outside the allowable bounds for this column
      col.width = constrainWidth(col, maxWidth);

      // All other columns because fixed to their drawn width, if they aren't already
      resizeAroundColumn(col);

      buildColumnsAndRefresh(xDiff);

      uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);
    });
3
votes

So, this worked for me when I needed to shrink all columns except for one. I iterate through all columns after the grid is finished loading, and trigger a double click event on the resizer. Not the prettiest, so if anybody else has a better solution, I'd be very happy to hear it!

function resizeColumn(uid) {
    // document.querySelector might not be supported; if you have jQuery
    // in your project, it might be wise to use that for selecting this
    // element instead
    var resizer = document.querySelector('.ui-grid-col' + uid + ' .ui-grid-column-resizer.right');
    angular.element(resizer).triggerHandler('dblclick');
}

var gridOptions = {
    ...
    onRegisterApi: function (gridApi) {
        // why $interval instead of $timeout? beats me, I'm not smart enough
        // to figure out why, but $timeout repeated infinitely for me
        $interval(function() {
            var columns = gridApi.grid.columns;
            for(var i = 0; i < columns.length; i++) {
                // your conditional here
                if(columns[i].field !== 'name') {
                    resizeColumn(columns[i].uid)
                }
            }
        }, 0, 1);
    }
}
2
votes

you can use * as in the width property - is consider as auto you can see here

2
votes

Using width : "*", will adjust all the columns in the available view port, which results in columns to get compressed.

Specifying minWidth: "somevalue" and width: "*" makes your ui-grid look better

0
votes

add the following to the gridoptions

                    init: function (gridCtrl, gridScope) {
                        gridScope.$on('ngGridEventData', function () {
                            $timeout(function () {
                                angular.forEach(gridScope.columns, function (col) {
                                    gridCtrl.resizeOnData(col);
                                });
                            });
                        });
                    }

Make sure you have a width of any random number on each column definition

width: 100 

is fine.

0
votes

I did not find any implementation for this so this is what I've done

  1. Iterated through the first 10 records.

  2. Found the max size of data for each column.

  3. Then created a span tag on the fly and wrapped it with that data.

  4. Measured the width of the tag and that would be your approx width required for the column (might need to append some more constant width due to CSS effect etc).

  5. If first 10 records are null then do the same process but this time with column header.

0
votes

Best solution I can come up with is to:

  1. set the grid width to 100%
  2. set the maxWidth: attribute on the columnDefs you don't want to size to some small number
  3. let the grid size itself

html:

ui-grid="gridOptions" class="myuigrid" ui-ui-grid-resize-columns ui-grid-ui-grid-auto-resize></div>

css:

.myuigrid {
   width: 100%;
 }

js

            columnDefs: [
              { name: 'Id', maxWidth:80 },
              { name: 'Name', maxWidth: 280 },
              { name: 'LongName'},
            ],

I know this won't work in every case but a lot of the time most of your columns are more or less fixed and the variable ones which you know in advance are the ones to let resize.

0
votes

I found some issues with width solution. We should use the property 'cellClass' in ui-grid columns object to enable this class.

.ui-grid-cell-contents-auto {
     /* Old Solution */
    /*min-width: max-content !important;*/

    /* New Solution */
    display: grid;
    grid-auto-columns: max-content;

    /* IE Solution */
    display: -ms-grid;
    -ms-grid-columns: max-content;
}

then you should use the property cellClass in ui-grid columns object to enable this class on your grid (something like this):

columns: [{ field: 'search_name', displayName: '', cellClass: 'ui-grid-cell-contents-auto'}]

You can refer to nekhaly's answer detailed description. https://github.com/angular-ui/ui-grid/issues/3913

0
votes

You can use following code:

<div ui-grid="gridOptions" class="grid" ui-grid-auto-resize></div>

var app = angular.module('app', ['ui.grid', 'ui.grid.autoResize']);

For reference you check the ui-grid documentation here.

-2
votes

try using 'width: auto' ..apparently using this was an issue in a previous release of ui-grid, it should work now, its part of their docs here: defining columns

EDIT: reference link to closed issue #565 page