Skip to content

Commit

Permalink
fix(scaleColumns): adjust for overflow when scaling columns in flex m…
Browse files Browse the repository at this point in the history
…ode (#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
  • Loading branch information
peter-stoyanov authored Feb 8, 2024
1 parent 0379785 commit a6dbc95
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 5 deletions.
49 changes: 48 additions & 1 deletion projects/ngx-datatable/src/lib/utils/math.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { forceFillColumnWidths } from './math';
import { adjustColumnWidths, forceFillColumnWidths } from './math';

describe('Math function', () => {
describe('forceFillColumnWidths', () => {
Expand Down Expand Up @@ -34,4 +34,51 @@ describe('Math function', () => {
});
});
});

describe('adjustColumnWidths', () => {
describe('flex mode', () => {
it('should not go over/under compared to given max width', () => {
const cols = [
{ prop: 'id1', width: 287, maxWidth: undefined, minWidth: 175, flexGrow: 2, canAutoResize: true },
{ prop: 'id2', width: 215, maxWidth: undefined, minWidth: 200, flexGrow: 1.5, canAutoResize: true },
{ prop: 'id3', width: 287, maxWidth: undefined, minWidth: 150, flexGrow: 2, canAutoResize: true },
{ prop: 'id4', width: 175, maxWidth: undefined, minWidth: 175, flexGrow: 1, canAutoResize: true },
{ prop: 'id5', width: 143, maxWidth: undefined, minWidth: 120, flexGrow: 1, canAutoResize: true }
];

const givenTableWidth = 1180;

adjustColumnWidths(cols, givenTableWidth);

const totalAdjustedColumnWidths = cols.map(c => c.width).reduce((p, c) => p + c, 0);
expect(totalAdjustedColumnWidths).toBeCloseTo(givenTableWidth, 0.001);
});

it('should overflow if the total of given min widths is bigger than given max width', () => {
const cols = [
{ prop: 'id1', width: 100, maxWidth: undefined, minWidth: 100, flexGrow: 1, canAutoResize: true },
{ prop: 'id2', width: 100, maxWidth: undefined, minWidth: 100, flexGrow: 1, canAutoResize: true }
];
const maxWidth = 199;

adjustColumnWidths(cols, maxWidth);

const totalAdjustedColumnWidths = cols.map(c => c.width).reduce((p, c) => p + c, 0);
expect(totalAdjustedColumnWidths).toBeGreaterThan(maxWidth);
});

it('should respect min widths', () => {
const cols = [
{ prop: 'id1', width: 0, maxWidth: undefined, minWidth: 10, flexGrow: 3.0000000000000075, canAutoResize: true },
{ prop: 'id2', width: 0, maxWidth: undefined, minWidth: 10, flexGrow: 1, canAutoResize: true }
];

adjustColumnWidths(cols, 40);

for (const col of cols) {
expect(col.width - col.minWidth).toBeGreaterThanOrEqual(0);
}
});
});
});
});
34 changes: 30 additions & 4 deletions projects/ngx-datatable/src/lib/utils/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export function adjustColumnWidths(allColumns: any, expectedWidth: any) {
* Resizes columns based on the flexGrow property, while respecting manually set widths
*/
function scaleColumns(colsByGroup: any, maxWidth: any, totalFlexGrow: any) {
// calculate total width and flexgrow points for coulumns that can be resized
// calculate total width and flexgrow points for columns that can be resized
for (const attr in colsByGroup) {
if (colsByGroup.hasOwnProperty(attr)){
if (colsByGroup.hasOwnProperty(attr)) {
for (const column of colsByGroup[attr]) {
if (column.$$oldWidth) {
// when manually resized, switch off auto-resize
Expand All @@ -58,9 +58,9 @@ function scaleColumns(colsByGroup: any, maxWidth: any, totalFlexGrow: any) {
remainingWidth = 0;

for (const attr in colsByGroup) {
if (colsByGroup.hasOwnProperty(attr)){
if (colsByGroup.hasOwnProperty(attr)) {
for (const column of colsByGroup[attr]) {
// if the column can be resize and it hasn't reached its minimum width yet
// if the column can be resize and it hasn't reached its minimum width yet
if (column.canAutoResize && !hasMinWidth[column.prop]) {
const newWidth = column.width + column.flexGrow * widthPerFlexPoint;
if (column.minWidth !== undefined && newWidth < column.minWidth) {
Expand All @@ -75,6 +75,32 @@ function scaleColumns(colsByGroup: any, maxWidth: any, totalFlexGrow: any) {
}
}
} while (remainingWidth !== 0);

// Adjust for any remaining offset in computed widths vs maxWidth
const columns = Object.values<{
width: number,
canAutoResize: boolean,
minWidth: number,
maxWidth: number
}>(colsByGroup).reduce((acc, col) => acc.concat(col), []);

const totalWidthAchieved = columns.reduce((acc, col) => acc + col.width, 0);
const delta = maxWidth - totalWidthAchieved;

if (delta === 0) {
return
}

// adjust the first column that can be auto-resized respecting the min/max widths
for (const col of columns.filter(c => c.canAutoResize).sort((a, b) => a.width - b.width)) {
if (
(delta > 0 && (!col.maxWidth || col.width + delta <= col.maxWidth)) ||
(delta < 0 && (!col.minWidth || col.width + delta >= col.minWidth))
) {
col.width += delta;
break;
}
}
}

/**
Expand Down

0 comments on commit a6dbc95

Please sign in to comment.