Skip to content

Commit

Permalink
refactor: use signals to render internal rows
Browse files Browse the repository at this point in the history
- Switched to use signal for `temp` iterator which was used for rendering the rows on view also renamed `temp` to `rowsToRender`.
- `getRowsStyles` and `bottomSummaryRowsStyles` converted to `computed` signals to avoid calling them unnecessarily. This should lead to some performance boost.
  • Loading branch information
chintankavathia authored and timowolf committed Oct 9, 2024
1 parent a33936d commit fa1f611
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('DataTableBodyComponent', () => {

describe('Summary row', () => {
it('should not return custom styles for a bottom summary row if a scrollbar mode is off', () => {
const styles = component.getBottomSummaryRowStyles();
const styles = component.bottomSummaryRowsStyles();
expect(styles).toBeFalsy();
});

Expand All @@ -124,7 +124,7 @@ describe('DataTableBodyComponent', () => {
component.scrollbarV = true;
component.virtualization = true;
component.rows = [{ num: 1 }, { num: 2 }, { num: 3 }, { num: 4 }];
const styles = component.getBottomSummaryRowStyles();
const styles = component.bottomSummaryRowsStyles();
expect(styles).toBeDefined();
});
});
Expand Down
90 changes: 48 additions & 42 deletions projects/ngx-datatable/src/lib/components/body/body.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
computed,
EventEmitter,
HostBinding,
inject,
Input,
OnDestroy,
OnInit,
Output,
signal,
TemplateRef,
TrackByFunction,
ViewChild
Expand Down Expand Up @@ -86,12 +88,12 @@ import {
>
</datatable-summary-row>
}
@for (group of temp; track rowTrackingFn(i, group); let i = $index) {
@for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
<datatable-row-wrapper
#rowWrapper
[groupedRows]="groupedRows"
[innerWidth]="innerWidth"
[ngStyle]="getRowsStyles(group, indexes.first + i)"
[ngStyle]="rowsStyles()[i]"
[rowDetail]="rowDetail"
[groupHeader]="groupHeader"
[offsetX]="offsetX"
Expand Down Expand Up @@ -218,7 +220,7 @@ import {
@if (summaryRow && summaryPosition === 'bottom') {
<datatable-summary-row
role="row"
[ngStyle]="getBottomSummaryRowStyles()"
[ngStyle]="bottomSummaryRowsStyles()"
[rowHeight]="summaryHeight"
[offsetX]="offsetX"
[innerWidth]="innerWidth"
Expand Down Expand Up @@ -264,7 +266,7 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
this._ghostLoadingIndicator = val;
if (!val) {
// remove placeholder rows once ghostloading is set to false
this.temp = this.temp.filter(item => !!item);
this.rowsToRender.set(this.rowsToRender().filter(item => !!item));
}
}
get ghostLoadingIndicator() {
Expand Down Expand Up @@ -418,7 +420,7 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
}

rowHeightsCache: RowHeightCache = new RowHeightCache();
temp: RowOrGroup<TRow>[] = [];
rowsToRender = signal<RowOrGroup<TRow>[]>([]);
offsetY = 0;
indexes: any = {};
columnGroupWidths: ColumnGroupWidth;
Expand Down Expand Up @@ -538,9 +540,13 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
this.offsetY = scrollYPos;
this.offsetX = scrollXPos;

const prevIndexes = { ...this.indexes };
this.updateIndexes();
this.updatePage(event.direction);
this.updateRows();
// only call updateRows if indexes are changed
if (prevIndexes.first !== this.indexes.first || prevIndexes.last !== this.indexes.last) {
this.updateRows();
}
this.cd.detectChanges();
}

Expand Down Expand Up @@ -628,8 +634,7 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
rowIndex++;
}
}

this.temp = temp;
this.rowsToRender.set(temp);
}

/**
Expand Down Expand Up @@ -710,58 +715,59 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
* case the positionY of the translate3d for row2 would be the sum of all the
* heights of the rows before it (i.e. row0 and row1).
*
* @param rows the row that needs to be placed in the 2D space.
* @param index for ghost cells in order to get correct position of ghost row
* @returns the CSS3 style to be applied
*
* @memberOf DataTableBodyComponent
*/
getRowsStyles(rows: RowOrGroup<TRow> | TRow[], index = 0): NgStyle['ngStyle'] {
const styles: NgStyle['ngStyle'] = {};

// only add styles for the group if there is a group
if (this.groupedRows) {
styles.width = this.columnGroupWidths.total;
}
rowsStyles = computed(() => {
const rowsStyles: NgStyle['ngStyle'][] = [];
this.rowsToRender().forEach((rows, index) => {
const styles: NgStyle['ngStyle'] = {};

// only add styles for the group if there is a group
if (this.groupedRows) {
styles.width = this.columnGroupWidths.total;
}

if (this.scrollbarV && this.virtualization) {
let idx = 0;
if (this.scrollbarV && this.virtualization) {
let idx = 0;

if (Array.isArray(rows)) {
// Get the latest row rowindex in a group
const row = rows[rows.length - 1];
idx = row ? this.getRowIndex(row) : 0;
} else {
if (rows) {
idx = this.getRowIndex(rows);
if (Array.isArray(rows)) {
// Get the latest row rowindex in a group
const row = rows[rows.length - 1];
idx = row ? this.getRowIndex(row) : 0;
} else {
// When ghost cells are enabled use index to get the position of them
idx = index;
if (rows) {
idx = this.getRowIndex(rows);
} else {
// When ghost cells are enabled use index to get the position of them
idx = this.indexes.first + index;
}
}
}

// const pos = idx * rowHeight;
// The position of this row would be the sum of all row heights
// until the previous row position.
const pos = this.rowHeightsCache.query(idx - 1);

Object.assign(styles, translateXY(0, pos));
}
// const pos = idx * rowHeight;
// The position of this row would be the sum of all row heights
// until the previous row position.
const pos = this.rowHeightsCache.query(idx - 1);

return styles;
}
Object.assign(styles, translateXY(0, pos));
}
rowsStyles.push(styles);
});
return rowsStyles;
});

/**
* Calculate bottom summary row offset for scrollbar mode.
* For more information about cache and offset calculation
* see description for `getRowsStyles` method
* see description for `rowsStyles` signal
*
* @returns the CSS3 style to be applied
*
* @memberOf DataTableBodyComponent
*/
getBottomSummaryRowStyles(): NgStyle['ngStyle'] {
if (!this.scrollbarV || !this.rows || !this.rows.length) {
bottomSummaryRowsStyles = computed(() => {
if (!this.scrollbarV || !this.rows || !this.rows.length || !this.rowsToRender()) {
return null;
}

Expand All @@ -770,7 +776,7 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
...translateXY(0, pos),
position: 'absolute'
};
}
});

/**
* Hides the loading indicator
Expand Down

0 comments on commit fa1f611

Please sign in to comment.