Skip to content

Commit fee00cd

Browse files
committed
fix(uiGridHeader): Fix header height growth bug
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
1 parent 5580ccb commit fee00cd

File tree

3 files changed

+61
-20
lines changed

3 files changed

+61
-20
lines changed

src/js/core/directives/ui-grid-header.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
$scope.grid = uiGridCtrl.grid;
2222
$scope.colContainer = containerCtrl.colContainer;
2323

24-
25-
26-
containerCtrl.header = $elm;
27-
containerCtrl.colContainer.header = $elm;
24+
updateHeaderReferences();
2825

2926
var headerTemplate;
3027
if (!$scope.grid.options.showHeader) {
@@ -34,20 +31,18 @@
3431
headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;
3532
}
3633

37-
gridUtil.getTemplate(headerTemplate)
34+
gridUtil.getTemplate(headerTemplate)
3835
.then(function (contents) {
3936
var template = angular.element(contents);
4037

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

44-
// Replace the reference to the container's header element with this new element
45-
containerCtrl.header = newElm;
46-
containerCtrl.colContainer.header = newElm;
47-
4841
// And update $elm to be the new element
4942
$elm = newElm;
5043

44+
updateHeaderReferences();
45+
5146
if (containerCtrl) {
5247
// Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
5348
var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
@@ -57,6 +52,19 @@
5752
}
5853
}
5954
});
55+
56+
function updateHeaderReferences() {
57+
containerCtrl.header = containerCtrl.colContainer.header = $elm;
58+
59+
var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');
60+
61+
if (headerCanvases.length > 0) {
62+
containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];
63+
}
64+
else {
65+
containerCtrl.headerCanvas = null;
66+
}
67+
}
6068
},
6169

6270
post: function ($scope, $elm, $attrs, controllers) {

src/js/core/directives/ui-grid-render-container.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,12 @@
197197
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';
198198

199199
// 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)
200-
if (renderContainer.explicitHeaderHeight !== undefined && renderContainer.explicitHeaderHeight !== null && renderContainer.explicitHeaderHeight > 0) {
201-
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.explicitHeaderHeight + 'px; }';
200+
if (renderContainer.explicitHeaderCanvasHeight !== undefined && renderContainer.explicitHeaderCanvasHeight !== null && renderContainer.explicitHeaderCanvasHeight > 0) {
201+
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
202202
}
203-
// 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)
204-
else if (renderContainer.innerHeaderHeight !== undefined && renderContainer.innerHeaderHeight !== null && renderContainer.innerHeaderHeight > 0) {
205-
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.innerHeaderHeight + 'px; }';
203+
// // 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)
204+
else if (renderContainer.headerCanvasHeight !== undefined && renderContainer.headerCanvasHeight !== null && renderContainer.headerCanvasHeight > 0) {
205+
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.headerCanvasHeight + 'px; }';
206206
}
207207

208208
return ret;

src/js/core/factories/Grid.js

+39-6
Original file line numberDiff line numberDiff line change
@@ -1882,12 +1882,24 @@ angular.module('ui.grid')
18821882
continue;
18831883
}
18841884

1885-
if (container.header) {
1885+
if (container.header || container.headerCanvas) {
18861886
containerHeadersToRecalc.push(container);
18871887
}
18881888
}
18891889
}
18901890

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

18991911
// Get all the header heights
1900-
var maxHeight = 0;
1912+
var maxHeaderHeight = 0;
1913+
var maxHeaderCanvasHeight = 0;
19011914
var i, container;
19021915
for (i = 0; i < containerHeadersToRecalc.length; i++) {
19031916
container = containerHeadersToRecalc[i];
@@ -1927,8 +1940,24 @@ angular.module('ui.grid')
19271940
container.innerHeaderHeight = innerHeaderHeight;
19281941

19291942
// Save the largest header height for use later
1930-
if (innerHeaderHeight > maxHeight) {
1931-
maxHeight = innerHeaderHeight;
1943+
if (innerHeaderHeight > maxHeaderHeight) {
1944+
maxHeaderHeight = innerHeaderHeight;
1945+
}
1946+
}
1947+
1948+
if (container.headerCanvas) {
1949+
var oldHeaderCanvasHeight = container.headerCanvasHeight;
1950+
var headerCanvasHeight = gridUtil.outerElementHeight(container.headerCanvas);
1951+
1952+
container.headerCanvasHeight = parseInt(headerCanvasHeight, 10);
1953+
1954+
if (oldHeaderCanvasHeight !== headerCanvasHeight) {
1955+
rebuildStyles = true;
1956+
}
1957+
1958+
// Save the largest header canvas height for use later
1959+
if (headerCanvasHeight > maxHeaderCanvasHeight) {
1960+
maxHeaderCanvasHeight = headerCanvasHeight;
19321961
}
19331962
}
19341963
}
@@ -1938,8 +1967,12 @@ angular.module('ui.grid')
19381967
container = containerHeadersToRecalc[i];
19391968

19401969
// 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
1941-
if (container.headerHeight < maxHeight) {
1942-
container.explicitHeaderHeight = maxHeight;
1970+
if (container.headerHeight < maxHeaderHeight) {
1971+
container.explicitHeaderHeight = maxHeaderHeight;
1972+
}
1973+
1974+
if (container.headerCanvasHeight < maxHeaderCanvasHeight) {
1975+
container.explicitHeaderCanvasHeight = maxHeaderCanvasHeight;
19431976
}
19441977
}
19451978

0 commit comments

Comments
 (0)