Skip to content

Commit b2ec710

Browse files
committed
feat: resize column to fit content on double click
1 parent 06a9fe6 commit b2ec710

File tree

5 files changed

+79
-1
lines changed

5 files changed

+79
-1
lines changed

projects/ngx-datatable/src/lib/components/body/body-row.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { DataTableBodyCellComponent } from './body-cell.component';
4343
<datatable-body-cell
4444
role="cell"
4545
tabindex="-1"
46+
[attr.header-id]="column.$$id"
4647
[row]="row"
4748
[group]="group"
4849
[expanded]="expanded"

projects/ngx-datatable/src/lib/components/datatable.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
(sort)="onColumnSort($event)"
2424
(resize)="onColumnResize($event)"
2525
(resizing)="onColumnResizing($event)"
26+
(fitToContent)="onColumnFitToContent($event)"
2627
(reorder)="onColumnReorder($event)"
2728
(select)="onHeaderSelect()"
2829
(columnContextmenu)="onColumnContextmenu($event)"

projects/ngx-datatable/src/lib/components/datatable.component.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ export class DatatableComponent<TRow extends Row = any>
906906
}
907907

908908
/**
909-
* Recalulcates the column widths based on column width
909+
* Recalculates the column widths based on column width
910910
* distribution mode and scrollbar offsets.
911911
*/
912912
recalculateColumns(
@@ -1129,6 +1129,63 @@ export class DatatableComponent<TRow extends Row = any>
11291129
this.recalculateColumns(this._internalColumns, idx);
11301130
}
11311131

1132+
/**
1133+
* Triggered when double clicked on resize handler
1134+
*/
1135+
onColumnFitToContent({
1136+
headerElement,
1137+
column
1138+
}: {
1139+
headerElement: HTMLElement;
1140+
column: TableColumnInternal;
1141+
}): void {
1142+
const columnCells = Array.from(
1143+
this.bodyElement.nativeElement.querySelectorAll('datatable-body-cell')
1144+
);
1145+
1146+
const selectedColumnItems = columnCells.filter(
1147+
c => c.getAttribute('header-id') === column.$$id
1148+
);
1149+
1150+
// this element has to be a form, otherwise form elements within a cell
1151+
// will be validated while being cloned. This can cause issues such as
1152+
// radio buttons being reset and losing their values.
1153+
const eDummyContainer = document.createElement('form');
1154+
// position fixed, so it isn't restricted to the boundaries of the parent
1155+
eDummyContainer.style.position = 'fixed';
1156+
eDummyContainer.style.padding = '16px';
1157+
1158+
const eBodyContainer = this.bodyElement.nativeElement;
1159+
1160+
selectedColumnItems
1161+
.concat(headerElement)
1162+
.forEach(el => this.cloneItemIntoDummy(el, eDummyContainer));
1163+
1164+
eBodyContainer.appendChild(eDummyContainer);
1165+
1166+
const dummyContainerWidth = eDummyContainer.offsetWidth;
1167+
1168+
// we are finished with the dummy container, so get rid of it
1169+
eBodyContainer.removeChild(eDummyContainer);
1170+
1171+
this.onColumnResize({ column, newValue: dummyContainerWidth, prevValue: column.width });
1172+
}
1173+
1174+
private cloneItemIntoDummy(eCell: Element, eDummyContainer: HTMLElement): void {
1175+
// make a deep clone of the cell
1176+
const eCellClone: HTMLElement = eCell.cloneNode(true) as HTMLElement;
1177+
// the original has a fixed width, we remove this to allow the natural width based on content
1178+
eCellClone.style.width = '';
1179+
// the original has position = absolute, we need to remove this so it's positioned normally
1180+
eCellClone.style.position = 'static';
1181+
eCellClone.style.left = '';
1182+
1183+
const eCloneParent = document.createElement('div');
1184+
1185+
eCloneParent.append(eCellClone);
1186+
eDummyContainer.appendChild(eCloneParent);
1187+
}
1188+
11321189
/**
11331190
* The header triggered a column re-order event.
11341191
*/

projects/ngx-datatable/src/lib/components/header/header-cell.component.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export class DataTableHeaderCellComponent implements OnInit, OnDestroy {
132132
}>(false);
133133
@Output() resize = new EventEmitter<{ width: number; column: TableColumnInternal }>();
134134
@Output() resizing = new EventEmitter<{ width: number; column: TableColumnInternal }>();
135+
@Output() fitToContent = new EventEmitter<HTMLElement>();
135136

136137
@HostBinding('class')
137138
get columnCssClasses(): string {
@@ -234,6 +235,15 @@ export class DataTableHeaderCellComponent implements OnInit, OnDestroy {
234235
this.onSort();
235236
}
236237

238+
@HostListener('dblclick', ['$event'])
239+
onDblClick(event: MouseEvent): void {
240+
const isHandle = (event.target as HTMLElement).classList.contains('resize-handle');
241+
if (isHandle) {
242+
event.stopPropagation();
243+
this.fitToContent.emit(this.element);
244+
}
245+
}
246+
237247
ngOnInit() {
238248
this.sortClass = this.calcSortClass(this.sortDir);
239249
// If there is already a default sort then start the counter with 1.

projects/ngx-datatable/src/lib/components/header/header.component.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import { OrderableDirective } from '../../directives/orderable.directive';
6060
role="columnheader"
6161
(resize)="onColumnResized($event)"
6262
(resizing)="onColumnResizing($event)"
63+
(fitToContent)="onColumnFitToContent($event, column)"
6364
long-press
6465
[pressModel]="column"
6566
[pressEnabled]="reorderable && column.draggable"
@@ -191,6 +192,10 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges {
191192
event: MouseEvent;
192193
column: TableColumnInternal;
193194
}>(false);
195+
@Output() fitToContent = new EventEmitter<{
196+
headerElement: HTMLElement;
197+
column: TableColumnInternal;
198+
}>();
194199

195200
_columnsByPin!: PinnedColumns[];
196201
_columnGroupWidths: any = {
@@ -267,6 +272,10 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges {
267272
this.resizing.emit(this.makeResizeEvent(width, column));
268273
}
269274

275+
onColumnFitToContent(headerElement: HTMLElement, column: TableColumnInternal) {
276+
this.fitToContent.emit({ headerElement, column });
277+
}
278+
270279
private makeResizeEvent(
271280
width: number,
272281
column: TableColumnInternal<Row>

0 commit comments

Comments
 (0)