Skip to content

Commit fdb6355

Browse files
authored
Merge pull request #7662 from IgniteUI/mkirova/resizing-percentage-width
Add support for Column Resizing and AutoSizing of % widths
2 parents 710523f + 94f9d0d commit fdb6355

File tree

7 files changed

+291
-60
lines changed

7 files changed

+291
-60
lines changed

projects/igniteui-angular/src/lib/grids/columns/column.component.ts

+60-4
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,44 @@ export class IgxColumnComponent implements AfterContentInit {
439439
@WatchColumnChanges()
440440
@Input()
441441
public maxWidth: string;
442+
443+
/**
444+
* @hidden
445+
*/
446+
get maxWidthPx() {
447+
const gridAvailableSize = this.grid.calcWidth;
448+
const isPercentageWidth = this.maxWidth && typeof this.maxWidth === 'string' && this.maxWidth.indexOf('%') !== -1;
449+
return isPercentageWidth ? parseFloat(this.maxWidth) / 100 * gridAvailableSize : parseFloat(this.maxWidth);
450+
}
451+
452+
/**
453+
* @hidden
454+
*/
455+
get maxWidthPercent() {
456+
const gridAvailableSize = this.grid.calcWidth;
457+
const isPercentageWidth = this.maxWidth && typeof this.maxWidth === 'string' && this.maxWidth.indexOf('%') !== -1;
458+
return isPercentageWidth ? parseFloat(this.maxWidth) : parseFloat(this.maxWidth) / gridAvailableSize * 100;
459+
}
460+
461+
/**
462+
* @hidden
463+
*/
464+
get minWidthPx() {
465+
const gridAvailableSize = this.grid.calcWidth;
466+
const isPercentageWidth = this.minWidth && typeof this.minWidth === 'string' && this.minWidth.indexOf('%') !== -1;
467+
return isPercentageWidth ? parseFloat(this.minWidth) / 100 * gridAvailableSize : parseFloat(this.minWidth);
468+
}
469+
470+
/**
471+
* @hidden
472+
*/
473+
get minWidthPercent() {
474+
const gridAvailableSize = this.grid.calcWidth;
475+
const isPercentageWidth = this.minWidth && typeof this.minWidth === 'string' && this.minWidth.indexOf('%') !== -1;
476+
return isPercentageWidth ? parseFloat(this.minWidth) : parseFloat(this.minWidth) / gridAvailableSize * 100;
477+
}
478+
479+
442480
/**
443481
* Sets/gets the minimum `width` of the column.
444482
* Default value is `88`;
@@ -1754,12 +1792,30 @@ export class IgxColumnComponent implements AfterContentInit {
17541792
*/
17551793
public autosize(byHeader = false) {
17561794
if (!this.columnGroup) {
1757-
this.width = !byHeader ? this.getLargestCellWidth() :
1758-
(Object.values(this.getHeaderCellWidths()).reduce((a, b) => a + b) + 'px');
1795+
const size = this.getAutoSize(byHeader);
1796+
this.width = size;
17591797
this.grid.reflow();
17601798
}
17611799
}
17621800

1801+
/**
1802+
* @hidden
1803+
*/
1804+
public getAutoSize(byHeader = false) {
1805+
const size = !byHeader ? this.getLargestCellWidth() :
1806+
(Object.values(this.getHeaderCellWidths()).reduce((a, b) => a + b) + 'px');
1807+
const gridAvailableSize = this.grid.calcWidth;
1808+
let newWidth;
1809+
const isPercentageWidth = this.width && typeof this.width === 'string' && this.width.indexOf('%') !== -1;
1810+
if (isPercentageWidth) {
1811+
const percentageSize = parseFloat(size) / gridAvailableSize * 100;
1812+
newWidth = percentageSize + '%';
1813+
} else {
1814+
newWidth = size;
1815+
}
1816+
return newWidth;
1817+
}
1818+
17631819
/**
17641820
* @hidden
17651821
*/
@@ -1880,14 +1936,14 @@ export class IgxColumnComponent implements AfterContentInit {
18801936
const colWidth = this.width;
18811937
const isPercentageWidth = colWidth && typeof colWidth === 'string' && colWidth.indexOf('%') !== -1;
18821938
if (isPercentageWidth) {
1883-
this._calcWidth = parseInt(colWidth, 10) / 100 * grid.calcWidth;
1939+
this._calcWidth = parseFloat(colWidth) / 100 * grid.calcWidth;
18841940
} else if (!colWidth) {
18851941
// no width
18861942
this._calcWidth = this.defaultWidth || grid.getPossibleColumnWidth();
18871943
} else {
18881944
this._calcWidth = this.width;
18891945
}
1890-
this.calcPixelWidth = parseInt(this._calcWidth, 10);
1946+
this.calcPixelWidth = parseFloat(this._calcWidth);
18911947
}
18921948

18931949
/**

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3552,7 +3552,7 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
35523552
if (this.hasColumnLayouts) {
35533553
return '';
35543554
}
3555-
const colWidth = parseInt(column.calcWidth, 10);
3555+
const colWidth = parseFloat(column.calcWidth);
35563556
const minWidth = this.defaultHeaderGroupMinWidth;
35573557

35583558
if (colWidth < minWidth) {

projects/igniteui-angular/src/lib/grids/grid/column-resizing.spec.ts

+147-4
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,149 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => {
425425
}));
426426
});
427427

428+
describe('Percentage tests: ', () => {
429+
let fixture: ComponentFixture<any>;
430+
let grid: IgxGridComponent;
431+
432+
beforeEach(fakeAsync(() => {
433+
fixture = TestBed.createComponent(ColPercentageGridComponent);
434+
fixture.detectChanges();
435+
grid = fixture.componentInstance.grid;
436+
}));
437+
438+
it('should resize columns with % width.', fakeAsync(() => {
439+
grid.height = null;
440+
fixture.detectChanges();
441+
const headers = GridFunctions.getColumnHeaders(fixture);
442+
expect(grid.columns[0].width).toBe('25%');
443+
444+
const headerResArea = headers[0].parent.children[2].nativeElement;
445+
const startPos = headerResArea.getBoundingClientRect().x;
446+
UIInteractions.simulateMouseEvent('mousedown', headerResArea, startPos, 5);
447+
tick(200);
448+
fixture.detectChanges();
449+
450+
const resizer = GridFunctions.getResizer(fixture).nativeElement;
451+
expect(resizer).toBeDefined();
452+
// resize with 100px, which is 25%
453+
UIInteractions.simulateMouseEvent('mousemove', resizer, startPos + 100, 5);
454+
UIInteractions.simulateMouseEvent('mouseup', resizer, startPos + 100, 5);
455+
fixture.detectChanges();
456+
expect(grid.columns[0].width).toBe('50%');
457+
}));
458+
459+
it('should resize columns with % width and % maxWidth.', fakeAsync(() => {
460+
grid.height = null;
461+
fixture.detectChanges();
462+
const headers = GridFunctions.getColumnHeaders(fixture);
463+
grid.columns[0].maxWidth = '30%';
464+
expect(grid.columns[0].width).toBe('25%');
465+
466+
const headerResArea = headers[0].parent.children[2].nativeElement;
467+
const startPos = headerResArea.getBoundingClientRect().x;
468+
UIInteractions.simulateMouseEvent('mousedown', headerResArea, startPos, 5);
469+
tick(200);
470+
fixture.detectChanges();
471+
472+
const resizer = GridFunctions.getResizer(fixture).nativeElement;
473+
expect(resizer).toBeDefined();
474+
// resize with +100px, which is 25%
475+
UIInteractions.simulateMouseEvent('mousemove', resizer, startPos + 100, 5);
476+
UIInteractions.simulateMouseEvent('mouseup', resizer, startPos + 100, 5);
477+
fixture.detectChanges();
478+
479+
expect(grid.columns[0].width).toBe(grid.columns[0].maxWidth);
480+
}));
481+
482+
it('should resize columns with % width and % minWidth.', fakeAsync(() => {
483+
grid.height = null;
484+
fixture.detectChanges();
485+
const headers = GridFunctions.getColumnHeaders(fixture);
486+
grid.columns[0].minWidth = '10%';
487+
expect(grid.columns[0].width).toBe('25%');
488+
489+
const headerResArea = headers[0].parent.children[2].nativeElement;
490+
const startPos = headerResArea.getBoundingClientRect().x;
491+
UIInteractions.simulateMouseEvent('mousedown', headerResArea, startPos, 5);
492+
tick(200);
493+
fixture.detectChanges();
494+
495+
const resizer = GridFunctions.getResizer(fixture).nativeElement;
496+
// resize with -100px
497+
UIInteractions.simulateMouseEvent('mousemove', resizer, startPos - 100, 5);
498+
UIInteractions.simulateMouseEvent('mouseup', resizer, startPos - 100, 5);
499+
fixture.detectChanges();
500+
501+
expect(grid.columns[0].width).toBe(grid.columns[0].minWidth);
502+
}));
503+
504+
it('should resize columns with % width and pixel maxWidth.', fakeAsync(() => {
505+
grid.height = null;
506+
fixture.detectChanges();
507+
const headers = GridFunctions.getColumnHeaders(fixture);
508+
grid.columns[0].maxWidth = '200px';
509+
expect(grid.columns[0].width).toBe('25%');
510+
511+
const headerResArea = headers[0].parent.children[2].nativeElement;
512+
const startPos = headerResArea.getBoundingClientRect().x;
513+
UIInteractions.simulateMouseEvent('mousedown', headerResArea, startPos, 5);
514+
tick(200);
515+
fixture.detectChanges();
516+
517+
const resizer = GridFunctions.getResizer(fixture).nativeElement;
518+
expect(resizer).toBeDefined();
519+
// resize with +200px, which is 50%
520+
UIInteractions.simulateMouseEvent('mousemove', resizer, startPos + 200, 5);
521+
UIInteractions.simulateMouseEvent('mouseup', resizer, startPos + 200, 5);
522+
fixture.detectChanges();
523+
expect(grid.columns[0].width).toBe('50%');
524+
}));
525+
526+
it('should resize columns with % width and pixel minWidth.', fakeAsync(() => {
527+
grid.height = null;
528+
fixture.detectChanges();
529+
const headers = GridFunctions.getColumnHeaders(fixture);
530+
// minWidth is 12.5% of the grid width - 400px
531+
grid.columns[0].minWidth = '50px';
532+
expect(grid.columns[0].width).toBe('25%');
533+
534+
const headerResArea = headers[0].parent.children[2].nativeElement;
535+
const startPos = headerResArea.getBoundingClientRect().x;
536+
UIInteractions.simulateMouseEvent('mousedown', headerResArea, startPos, 5);
537+
tick(200);
538+
fixture.detectChanges();
539+
540+
const resizer = GridFunctions.getResizer(fixture).nativeElement;
541+
// resize with -100px
542+
UIInteractions.simulateMouseEvent('mousemove', resizer, startPos - 100, 5);
543+
UIInteractions.simulateMouseEvent('mouseup', resizer, startPos - 100, 5);
544+
fixture.detectChanges();
545+
546+
expect(grid.columns[0].width).toBe('12.5%');
547+
}));
548+
549+
it('should autosize column with % width programmatically.', fakeAsync(() => {
550+
grid.height = null;
551+
fixture.detectChanges();
552+
expect(grid.columns[0].width).toBe('25%');
553+
grid.columns[0].autosize();
554+
fixture.detectChanges();
555+
expect(grid.columns[0].width).toBe('21%');
556+
}));
557+
558+
it('should autosize column with % width on double click.', fakeAsync(() => {
559+
grid.height = null;
560+
fixture.detectChanges();
561+
expect(grid.columns[0].width).toBe('25%');
562+
const headers = GridFunctions.getColumnHeaders(fixture);
563+
const headerResArea = headers[0].parent.children[2].nativeElement;
564+
UIInteractions.simulateMouseEvent('dblclick', headerResArea, 0, 0);
565+
tick(200);
566+
fixture.detectChanges();
567+
expect(grid.columns[0].width).toBe('21%');
568+
}));
569+
});
570+
428571
describe('Integration tests: ', () => {
429572
let fixture: ComponentFixture<any>;
430573
let grid: IgxGridComponent;
@@ -453,8 +596,8 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => {
453596
UIInteractions.simulateMouseEvent('mouseup', resizer, 550, 5);
454597
fixture.detectChanges();
455598

456-
expect(grid.columns[2].width).toEqual('250px');
457-
expect(grid.columns[2].cells[0].value).toEqual(254);
599+
// column has maxWidth='150px'
600+
expect(grid.columns[1].width).toEqual('150px');
458601

459602
GridFunctions.clickHeaderSortIcon(headers[2]);
460603
GridFunctions.clickHeaderSortIcon(headers[2]);
@@ -508,7 +651,7 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => {
508651
UIInteractions.simulateMouseEvent('mouseup', resizer, 300, 5);
509652
fixture.detectChanges();
510653

511-
let resizingArgs: IColumnResizeEventArgs = { column: grid.columns[0], prevWidth: '150', newWidth: '300px' };
654+
let resizingArgs: IColumnResizeEventArgs = { column: grid.columns[0], prevWidth: '150px', newWidth: '300px' };
512655
expect(grid.columns[0].width).toEqual('300px');
513656
expect(resizingSpy).toHaveBeenCalledTimes(1);
514657
expect(resizingSpy).toHaveBeenCalledWith(resizingArgs);
@@ -805,7 +948,7 @@ export class ColGridComponent implements OnInit {
805948

806949
@Component({
807950
template: GridTemplateStrings.declareGrid(`width="400px" height="600px" [allowFiltering]="true"`, ``,
808-
`<igx-column [field]="'Items'" [width]="'25%'" dataType="string" [filterable]="true"></igx-column>
951+
`<igx-column [field]="'Items'" [width]="'25%'" dataType="string" [filterable]="true" [resizable]="true"></igx-column>
809952
<igx-column [field]="'ID'" [width]="'25%'" [header]="'ID'" [filterable]="true"></igx-column>
810953
<igx-column [field]="'ProductName'" [width]="'25%'" dataType="string" [filterable]="true"></igx-column>
811954
<igx-column [field]="'Test'"[width]="'25%'" dataType="string" [resizable]="true"></igx-column>`

0 commit comments

Comments
 (0)