Skip to content

Commit 2c99d95

Browse files
committed
fix(datatable-body): avoid multiple calculations and update properly on changes
1 parent 5b3dd8f commit 2c99d95

File tree

4 files changed

+241
-247
lines changed

4 files changed

+241
-247
lines changed

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

Lines changed: 16 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,24 @@ import {
1111
Input,
1212
KeyValueDiffer,
1313
KeyValueDiffers,
14-
OnChanges,
15-
Output,
16-
SimpleChanges
14+
Output
1715
} from '@angular/core';
1816

19-
import { columnGroupWidths, columnsByPin, columnsByPinArr } from '../../utils/column';
20-
import { Keys } from '../../utils/keys';
21-
import { ScrollbarHelper } from '../../services/scrollbar-helper.service';
22-
import { translateXY } from '../../utils/translate';
2317
import { BehaviorSubject } from 'rxjs';
24-
import { ActivateEvent, RowOrGroup, TreeStatus } from '../../types/public.types';
2518
import { NgStyle } from '@angular/common';
2619
import { TableColumn } from '../../types/table-column.type';
27-
import { ColumnGroupWidth, PinnedColumns } from '../../types/internal.types';
20+
import { ActivateEvent, RowOrGroup, TreeStatus } from '../../types/public.types';
21+
import { PinnedColumns } from '../../types/internal.types';
22+
import { Keys } from '../../utils/keys';
2823

2924
@Component({
3025
selector: 'datatable-body-row',
3126
changeDetection: ChangeDetectionStrategy.OnPush,
3227
template: `
33-
@for (colGroup of _columnsByPin; track colGroup.type; let i = $index) {
28+
@for (colGroup of columnsByPin; track colGroup.type; let i = $index) {
3429
<div
3530
class="datatable-row-{{ colGroup.type }} datatable-row-group"
36-
[ngStyle]="_groupStyles[colGroup.type]"
31+
[ngStyle]="groupStyles[colGroup.type]"
3732
[class.row-disabled]="disable$ ? (disable$ | async) : false"
3833
>
3934
@for (column of colGroup.columns; track column.$$id; let ii = $index) {
@@ -60,34 +55,12 @@ import { ColumnGroupWidth, PinnedColumns } from '../../types/internal.types';
6055
}
6156
`
6257
})
63-
export class DataTableBodyRowComponent<TRow = any> implements DoCheck, OnChanges {
64-
private scrollbarHelper = inject(ScrollbarHelper);
58+
export class DataTableBodyRowComponent<TRow = any> implements DoCheck {
6559
private cd = inject(ChangeDetectorRef);
6660

67-
@Input() set columns(val: TableColumn[]) {
68-
this._columns = val;
69-
this.recalculateColumns(val);
70-
this.buildStylesByGroup();
71-
}
61+
@Input() columns: TableColumn[];
7262

73-
get columns(): TableColumn[] {
74-
return this._columns;
75-
}
76-
77-
@Input() set innerWidth(val: number) {
78-
if (this._columns) {
79-
const colByPin = columnsByPin(this._columns);
80-
this._columnGroupWidths = columnGroupWidths(colByPin, this._columns);
81-
}
82-
83-
this._innerWidth = val;
84-
this.recalculateColumns();
85-
this.buildStylesByGroup();
86-
}
87-
88-
get innerWidth(): number {
89-
return this._innerWidth;
90-
}
63+
@Input() columnsByPin: PinnedColumns[];
9164

9265
@Input() expanded: boolean;
9366
@Input() rowClass?: (row: RowOrGroup<TRow>) => string | Record<string, boolean>;
@@ -98,124 +71,38 @@ export class DataTableBodyRowComponent<TRow = any> implements DoCheck, OnChanges
9871
@Input() displayCheck: (row: TRow, column: TableColumn, value?: any) => boolean;
9972
@Input() treeStatus?: TreeStatus = 'collapsed';
10073
@Input() ghostLoadingIndicator = false;
101-
@Input() verticalScrollVisible = false;
10274

10375
@Input() disable$: BehaviorSubject<boolean>;
104-
@Input()
105-
set offsetX(val: number) {
106-
this._offsetX = val;
107-
this.buildStylesByGroup();
108-
}
109-
get offsetX() {
110-
return this._offsetX;
111-
}
112-
113-
@HostBinding('class')
114-
get cssClass() {
115-
let cls = 'datatable-body-row';
116-
if (this.isSelected) {
117-
cls += ' active';
118-
}
119-
if (this.rowIndex % 2 !== 0) {
120-
cls += ' datatable-row-odd';
121-
}
122-
if (this.rowIndex % 2 === 0) {
123-
cls += ' datatable-row-even';
124-
}
125-
if (this.disable$ && this.disable$.value) {
126-
cls += ' row-disabled';
127-
}
12876

129-
if (this.rowClass) {
130-
const res = this.rowClass(this.row);
131-
if (typeof res === 'string') {
132-
cls += ` ${res}`;
133-
} else if (typeof res === 'object') {
134-
const keys = Object.keys(res);
135-
for (const k of keys) {
136-
if (res[k] === true) {
137-
cls += ` ${k}`;
138-
}
139-
}
140-
}
141-
}
77+
@HostBinding('class') @Input() cssClass: string;
14278

143-
return cls;
144-
}
79+
@Input() groupStyles: {
80+
left: NgStyle['ngStyle'];
81+
center: NgStyle['ngStyle'];
82+
right: NgStyle['ngStyle'];
83+
};
14584

14685
@HostBinding('style.height.px')
14786
@Input()
14887
rowHeight: number;
14988

150-
@HostBinding('style.width.px')
151-
get columnsTotalWidths(): number {
152-
return this._columnGroupWidths.total;
153-
}
89+
@HostBinding('style.width.px') @Input() columnsTotalWidth: number;
15490

15591
@Output() activate: EventEmitter<ActivateEvent<TRow>> = new EventEmitter();
15692
@Output() treeAction: EventEmitter<any> = new EventEmitter();
15793

15894
_element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;
159-
_columnGroupWidths: ColumnGroupWidth;
160-
_columnsByPin: PinnedColumns[];
161-
_offsetX: number;
162-
_columns: TableColumn[];
163-
_innerWidth: number;
164-
_groupStyles: {
165-
left: NgStyle['ngStyle'];
166-
center: NgStyle['ngStyle'];
167-
right: NgStyle['ngStyle'];
168-
} = { left: {}, center: {}, right: {} };
16995

17096
private _rowDiffer: KeyValueDiffer<keyof RowOrGroup<TRow>, any> = inject(KeyValueDiffers)
17197
.find({})
17298
.create();
17399

174-
ngOnChanges(changes: SimpleChanges): void {
175-
if (changes.verticalScrollVisible) {
176-
this.buildStylesByGroup();
177-
}
178-
}
179-
180100
ngDoCheck(): void {
181101
if (this._rowDiffer.diff(this.row)) {
182102
this.cd.markForCheck();
183103
}
184104
}
185105

186-
buildStylesByGroup() {
187-
this._groupStyles.left = this.calcStylesByGroup('left');
188-
this._groupStyles.center = this.calcStylesByGroup('center');
189-
this._groupStyles.right = this.calcStylesByGroup('right');
190-
this.cd.markForCheck();
191-
}
192-
193-
calcStylesByGroup(group: 'left' | 'right' | 'center') {
194-
const widths = this._columnGroupWidths;
195-
const offsetX = this.offsetX;
196-
197-
if (group === 'left') {
198-
return {
199-
width: `${widths[group]}px`,
200-
...translateXY(offsetX, 0)
201-
};
202-
} else if (group === 'right') {
203-
const bodyWidth = this.innerWidth;
204-
const totalDiff = widths.total - bodyWidth;
205-
const offsetDiff = totalDiff - offsetX;
206-
const offset =
207-
(offsetDiff + (this.verticalScrollVisible ? this.scrollbarHelper.width : 0)) * -1;
208-
return {
209-
width: `${widths[group]}px`,
210-
...translateXY(offset, 0)
211-
};
212-
}
213-
214-
return {
215-
width: `${widths[group]}px`
216-
};
217-
}
218-
219106
onActivate(event: ActivateEvent<TRow>, index: number): void {
220107
event.cellIndex = index;
221108
event.rowElement = this._element;
@@ -259,13 +146,6 @@ export class DataTableBodyRowComponent<TRow = any> implements DoCheck, OnChanges
259146
});
260147
}
261148

262-
recalculateColumns(val: TableColumn<TRow>[] = this.columns): void {
263-
this._columns = val;
264-
const colsByPin = columnsByPin(this._columns);
265-
this._columnsByPin = columnsByPinArr(this._columns);
266-
this._columnGroupWidths = columnGroupWidths(colsByPin, this._columns);
267-
}
268-
269149
onTreeAction() {
270150
this.treeAction.emit();
271151
}

0 commit comments

Comments
 (0)