Skip to content

Commit

Permalink
fix(uiGridHeader): Fix header height growth bug
Browse files Browse the repository at this point in the history
Header cells were growing in height due to a calculation bug where the
grid was reading the height of the entire header element rather than just
the repeater where the header cells were contained.  That means that a
custom header with extra stuff in it would cause headers to grow in height
on each canvas refresh.

This change splits header height calculations in two: one for the headers
themselves, which keeps headers between render containers consistent in
height, and another for header cells which uses the header canvas height
to keep header cells the same height.

Fixes #2781
  • Loading branch information
c0bra committed Feb 16, 2015
1 parent 5580ccb commit fee00cd
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 20 deletions.
26 changes: 17 additions & 9 deletions src/js/core/directives/ui-grid-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@
$scope.grid = uiGridCtrl.grid;
$scope.colContainer = containerCtrl.colContainer;



containerCtrl.header = $elm;
containerCtrl.colContainer.header = $elm;
updateHeaderReferences();

var headerTemplate;
if (!$scope.grid.options.showHeader) {
Expand All @@ -34,20 +31,18 @@
headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;
}

gridUtil.getTemplate(headerTemplate)
gridUtil.getTemplate(headerTemplate)
.then(function (contents) {
var template = angular.element(contents);

var newElm = $compile(template)($scope);
$elm.replaceWith(newElm);

// Replace the reference to the container's header element with this new element
containerCtrl.header = newElm;
containerCtrl.colContainer.header = newElm;

// And update $elm to be the new element
$elm = newElm;

updateHeaderReferences();

if (containerCtrl) {
// Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
Expand All @@ -57,6 +52,19 @@
}
}
});

function updateHeaderReferences() {
containerCtrl.header = containerCtrl.colContainer.header = $elm;

var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');

if (headerCanvases.length > 0) {
containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];
}
else {
containerCtrl.headerCanvas = null;
}
}
},

post: function ($scope, $elm, $attrs, controllers) {
Expand Down
10 changes: 5 additions & 5 deletions src/js/core/directives/ui-grid-render-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';

// If the render container has an "explicit" header height (such as in the case that its header is smaller than the other headers and needs to be explicitly set to be the same, ue thae)
if (renderContainer.explicitHeaderHeight !== undefined && renderContainer.explicitHeaderHeight !== null && renderContainer.explicitHeaderHeight > 0) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.explicitHeaderHeight + 'px; }';
if (renderContainer.explicitHeaderCanvasHeight !== undefined && renderContainer.explicitHeaderCanvasHeight !== null && renderContainer.explicitHeaderCanvasHeight > 0) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
}
// Otherwise if the render container has an INNER header height, use that on the header cells (so that all the header cells are the same height and those that have less elements don't have undersized borders)
else if (renderContainer.innerHeaderHeight !== undefined && renderContainer.innerHeaderHeight !== null && renderContainer.innerHeaderHeight > 0) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.innerHeaderHeight + 'px; }';
// // Otherwise if the render container has an INNER header height, use that on the header cells (so that all the header cells are the same height and those that have less elements don't have undersized borders)
else if (renderContainer.headerCanvasHeight !== undefined && renderContainer.headerCanvasHeight !== null && renderContainer.headerCanvasHeight > 0) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.headerCanvasHeight + 'px; }';
}

return ret;
Expand Down
45 changes: 39 additions & 6 deletions src/js/core/factories/Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -1882,12 +1882,24 @@ angular.module('ui.grid')
continue;
}

if (container.header) {
if (container.header || container.headerCanvas) {
containerHeadersToRecalc.push(container);
}
}
}

/*
*
* Here we loop through the headers, measuring each element as well as any header "canvas" it has within it.
*
* If any header is less than the largest header height, it will be resized to that so that we don't have headers
* with different heights, which looks like a rendering problem
*
* We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas
* is smaller than the largest canvas height. That was header cells without extra controls like filtering don't
* appear shorter than other cells.
*
*/
if (containerHeadersToRecalc.length > 0) {
// Putting in a timeout as it's not calculating after the grid element is rendered and filled out
$timeout(function() {
Expand All @@ -1897,7 +1909,8 @@ angular.module('ui.grid')
var rebuildStyles = false;

// Get all the header heights
var maxHeight = 0;
var maxHeaderHeight = 0;
var maxHeaderCanvasHeight = 0;
var i, container;
for (i = 0; i < containerHeadersToRecalc.length; i++) {
container = containerHeadersToRecalc[i];
Expand Down Expand Up @@ -1927,8 +1940,24 @@ angular.module('ui.grid')
container.innerHeaderHeight = innerHeaderHeight;

// Save the largest header height for use later
if (innerHeaderHeight > maxHeight) {
maxHeight = innerHeaderHeight;
if (innerHeaderHeight > maxHeaderHeight) {
maxHeaderHeight = innerHeaderHeight;
}
}

if (container.headerCanvas) {
var oldHeaderCanvasHeight = container.headerCanvasHeight;
var headerCanvasHeight = gridUtil.outerElementHeight(container.headerCanvas);

container.headerCanvasHeight = parseInt(headerCanvasHeight, 10);

if (oldHeaderCanvasHeight !== headerCanvasHeight) {
rebuildStyles = true;
}

// Save the largest header canvas height for use later
if (headerCanvasHeight > maxHeaderCanvasHeight) {
maxHeaderCanvasHeight = headerCanvasHeight;
}
}
}
Expand All @@ -1938,8 +1967,12 @@ angular.module('ui.grid')
container = containerHeadersToRecalc[i];

// If this header's height is less than another header's height, then explicitly set it so they're the same and one isn't all offset and weird looking
if (container.headerHeight < maxHeight) {
container.explicitHeaderHeight = maxHeight;
if (container.headerHeight < maxHeaderHeight) {
container.explicitHeaderHeight = maxHeaderHeight;
}

if (container.headerCanvasHeight < maxHeaderCanvasHeight) {
container.explicitHeaderCanvasHeight = maxHeaderCanvasHeight;
}
}

Expand Down

0 comments on commit fee00cd

Please sign in to comment.