Skip to content

Commit a6dbc95

Browse files
fix(scaleColumns): adjust for overflow when scaling columns in flex mode (#43)
* fix(scaleColumns): adjust for overflow when scaling columns in flex mode * fix(scaleColumns): handle null pointer for biggest column ref * fix(scaleColumns): respect min widths when applying fixes
1 parent 0379785 commit a6dbc95

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

projects/ngx-datatable/src/lib/utils/math.spec.ts

+48-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { forceFillColumnWidths } from './math';
1+
import { adjustColumnWidths, forceFillColumnWidths } from './math';
22

33
describe('Math function', () => {
44
describe('forceFillColumnWidths', () => {
@@ -34,4 +34,51 @@ describe('Math function', () => {
3434
});
3535
});
3636
});
37+
38+
describe('adjustColumnWidths', () => {
39+
describe('flex mode', () => {
40+
it('should not go over/under compared to given max width', () => {
41+
const cols = [
42+
{ prop: 'id1', width: 287, maxWidth: undefined, minWidth: 175, flexGrow: 2, canAutoResize: true },
43+
{ prop: 'id2', width: 215, maxWidth: undefined, minWidth: 200, flexGrow: 1.5, canAutoResize: true },
44+
{ prop: 'id3', width: 287, maxWidth: undefined, minWidth: 150, flexGrow: 2, canAutoResize: true },
45+
{ prop: 'id4', width: 175, maxWidth: undefined, minWidth: 175, flexGrow: 1, canAutoResize: true },
46+
{ prop: 'id5', width: 143, maxWidth: undefined, minWidth: 120, flexGrow: 1, canAutoResize: true }
47+
];
48+
49+
const givenTableWidth = 1180;
50+
51+
adjustColumnWidths(cols, givenTableWidth);
52+
53+
const totalAdjustedColumnWidths = cols.map(c => c.width).reduce((p, c) => p + c, 0);
54+
expect(totalAdjustedColumnWidths).toBeCloseTo(givenTableWidth, 0.001);
55+
});
56+
57+
it('should overflow if the total of given min widths is bigger than given max width', () => {
58+
const cols = [
59+
{ prop: 'id1', width: 100, maxWidth: undefined, minWidth: 100, flexGrow: 1, canAutoResize: true },
60+
{ prop: 'id2', width: 100, maxWidth: undefined, minWidth: 100, flexGrow: 1, canAutoResize: true }
61+
];
62+
const maxWidth = 199;
63+
64+
adjustColumnWidths(cols, maxWidth);
65+
66+
const totalAdjustedColumnWidths = cols.map(c => c.width).reduce((p, c) => p + c, 0);
67+
expect(totalAdjustedColumnWidths).toBeGreaterThan(maxWidth);
68+
});
69+
70+
it('should respect min widths', () => {
71+
const cols = [
72+
{ prop: 'id1', width: 0, maxWidth: undefined, minWidth: 10, flexGrow: 3.0000000000000075, canAutoResize: true },
73+
{ prop: 'id2', width: 0, maxWidth: undefined, minWidth: 10, flexGrow: 1, canAutoResize: true }
74+
];
75+
76+
adjustColumnWidths(cols, 40);
77+
78+
for (const col of cols) {
79+
expect(col.width - col.minWidth).toBeGreaterThanOrEqual(0);
80+
}
81+
});
82+
});
83+
});
3784
});

projects/ngx-datatable/src/lib/utils/math.ts

+30-4
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ export function adjustColumnWidths(allColumns: any, expectedWidth: any) {
3131
* Resizes columns based on the flexGrow property, while respecting manually set widths
3232
*/
3333
function scaleColumns(colsByGroup: any, maxWidth: any, totalFlexGrow: any) {
34-
// calculate total width and flexgrow points for coulumns that can be resized
34+
// calculate total width and flexgrow points for columns that can be resized
3535
for (const attr in colsByGroup) {
36-
if (colsByGroup.hasOwnProperty(attr)){
36+
if (colsByGroup.hasOwnProperty(attr)) {
3737
for (const column of colsByGroup[attr]) {
3838
if (column.$$oldWidth) {
3939
// when manually resized, switch off auto-resize
@@ -58,9 +58,9 @@ function scaleColumns(colsByGroup: any, maxWidth: any, totalFlexGrow: any) {
5858
remainingWidth = 0;
5959

6060
for (const attr in colsByGroup) {
61-
if (colsByGroup.hasOwnProperty(attr)){
61+
if (colsByGroup.hasOwnProperty(attr)) {
6262
for (const column of colsByGroup[attr]) {
63-
// if the column can be resize and it hasn't reached its minimum width yet
63+
// if the column can be resize and it hasn't reached its minimum width yet
6464
if (column.canAutoResize && !hasMinWidth[column.prop]) {
6565
const newWidth = column.width + column.flexGrow * widthPerFlexPoint;
6666
if (column.minWidth !== undefined && newWidth < column.minWidth) {
@@ -75,6 +75,32 @@ function scaleColumns(colsByGroup: any, maxWidth: any, totalFlexGrow: any) {
7575
}
7676
}
7777
} while (remainingWidth !== 0);
78+
79+
// Adjust for any remaining offset in computed widths vs maxWidth
80+
const columns = Object.values<{
81+
width: number,
82+
canAutoResize: boolean,
83+
minWidth: number,
84+
maxWidth: number
85+
}>(colsByGroup).reduce((acc, col) => acc.concat(col), []);
86+
87+
const totalWidthAchieved = columns.reduce((acc, col) => acc + col.width, 0);
88+
const delta = maxWidth - totalWidthAchieved;
89+
90+
if (delta === 0) {
91+
return
92+
}
93+
94+
// adjust the first column that can be auto-resized respecting the min/max widths
95+
for (const col of columns.filter(c => c.canAutoResize).sort((a, b) => a.width - b.width)) {
96+
if (
97+
(delta > 0 && (!col.maxWidth || col.width + delta <= col.maxWidth)) ||
98+
(delta < 0 && (!col.minWidth || col.width + delta >= col.minWidth))
99+
) {
100+
col.width += delta;
101+
break;
102+
}
103+
}
78104
}
79105

80106
/**

0 commit comments

Comments
 (0)