@@ -18,7 +18,7 @@ import {
1818import { ScrollerComponent } from './scroller.component' ;
1919import { columnGroupWidths , columnsByPin } from '../../utils/column' ;
2020import { RowHeightCache } from '../../utils/row-height-cache' ;
21- import { NgStyle , NgTemplateOutlet } from '@angular/common' ;
21+ import { NgTemplateOutlet } from '@angular/common' ;
2222import { DatatableGroupHeaderDirective } from './body-group-header.directive' ;
2323import { DatatableRowDetailDirective } from '../row-detail/row-detail.directive' ;
2424import { DataTableBodyRowComponent } from './body-row.component' ;
@@ -118,83 +118,84 @@ import { Keys } from '../../utils/keys';
118118 </datatable-body-row>
119119 </ng-template>
120120
121- @for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
122- @let disabled = isRow(group) && disableRowCheck && disableRowCheck(group);
123- <!-- $any(group) is needed as the typing is broken and the feature as well. See #147. -->
124- <!-- FIXME: This has to be revisited and fixed. -->
125- <datatable-row-wrapper
126- [attr.hidden]="
127- ghostLoadingIndicator && (!rowCount || !virtualization || !scrollbarV) ? true : null
128- "
129- [groupedRows]="groupedRows"
130- [innerWidth]="innerWidth"
131- [ngStyle]="rowsStyles()[i]"
132- [rowDetail]="rowDetail"
133- [groupHeader]="groupHeader"
134- [offsetX]="offsetX"
135- [detailRowHeight]="getDetailRowHeight(group && $any(group)[i], i)"
136- [groupHeaderRowHeight]="getGroupHeaderRowHeight(group && $any(group)[i], i)"
137- [row]="group"
138- [disabled]="disabled"
139- [expanded]="getRowExpanded(group)"
140- [rowIndex]="getRowIndex(group && $any(group)[i])?.index ?? 0"
141- [selected]="selected"
142- (rowContextmenu)="rowContextmenu.emit($event)"
143- >
144- @if (rowDefTemplate) {
145- <ng-container
146- *rowDefInternal="
147- {
148- template: rowDefTemplate,
149- rowTemplate: bodyRow,
150- row: group,
151- index: i
152- };
153- disabled: disabled
154- "
155- />
156- } @else {
157- @if (isRow(group)) {
121+ <div [style.transform]="renderOffset()">
122+ @for (group of rowsToRender(); track rowTrackingFn(i, group); let i = $index) {
123+ @let disabled = isRow(group) && disableRowCheck && disableRowCheck(group);
124+ <!-- $any(group) is needed as the typing is broken and the feature as well. See #147. -->
125+ <!-- FIXME: This has to be revisited and fixed. -->
126+ <datatable-row-wrapper
127+ [attr.hidden]="
128+ ghostLoadingIndicator && (!rowCount || !virtualization || !scrollbarV) ? true : null
129+ "
130+ [groupedRows]="groupedRows"
131+ [innerWidth]="innerWidth"
132+ [style.width]="groupedRows ? columnGroupWidths.total : undefined"
133+ [rowDetail]="rowDetail"
134+ [groupHeader]="groupHeader"
135+ [offsetX]="offsetX"
136+ [detailRowHeight]="getDetailRowHeight(group && $any(group)[i], i)"
137+ [groupHeaderRowHeight]="getGroupHeaderRowHeight(group && $any(group)[i], i)"
138+ [row]="group"
139+ [disabled]="disabled"
140+ [expanded]="getRowExpanded(group)"
141+ [rowIndex]="getRowIndex(group && $any(group)[i])?.index ?? 0"
142+ [selected]="selected"
143+ (rowContextmenu)="rowContextmenu.emit($event)"
144+ >
145+ @if (rowDefTemplate) {
158146 <ng-container
159- [ngTemplateOutlet]="bodyRow"
160- [ngTemplateOutletContext]="{
161- row: group,
162- index: i,
163- disabled
164- }"
165- ></ng-container>
147+ *rowDefInternal="
148+ {
149+ template: rowDefTemplate,
150+ rowTemplate: bodyRow,
151+ row: group,
152+ index: i
153+ };
154+ disabled: disabled
155+ "
156+ />
157+ } @else {
158+ @if (isRow(group)) {
159+ <ng-container
160+ [ngTemplateOutlet]="bodyRow"
161+ [ngTemplateOutletContext]="{
162+ row: group,
163+ index: i,
164+ disabled
165+ }"
166+ ></ng-container>
167+ }
166168 }
167- }
168169
169- @if (isGroup(group)) {
170- <!-- The row typecast is due to angular compiler acting weird. It is obvious that it is of type TRow, but the compiler does not understand. -->
171- @for (row of group.value; track rowTrackingFn(i, row); let i = $index) {
172- @let disabled = disableRowCheck && disableRowCheck(row);
173- <ng-container
174- [ngTemplateOutlet]="bodyRow"
175- [ngTemplateOutletContext]="{
176- row,
177- groupedRows: group?.value,
178- index: i,
179- disabled
180- }"
181- ></ng-container>
170+ @if (isGroup(group)) {
171+ <!-- The row typecast is due to angular compiler acting weird. It is obvious that it is of type TRow, but the compiler does not understand. -->
172+ @for (row of group.value; track rowTrackingFn(i, row); let i = $index) {
173+ @let disabled = disableRowCheck && disableRowCheck(row);
174+ <ng-container
175+ [ngTemplateOutlet]="bodyRow"
176+ [ngTemplateOutletContext]="{
177+ row,
178+ groupedRows: group?.value,
179+ index: i,
180+ disabled
181+ }"
182+ ></ng-container>
183+ }
182184 }
183- }
184- </datatable-row-wrapper>
185- }
186- @if (summaryRow && summaryPosition === 'bottom') {
187- <datatable-summary-row
188- role="row"
189- [ngStyle]="bottomSummaryRowsStyles()"
190- [rowHeight]="summaryHeight"
191- [innerWidth]="innerWidth"
192- [rows]="rows"
193- [columns]="columns"
194- >
195- </datatable-summary-row>
196- }
185+ </datatable-row-wrapper>
186+ }
187+ </div>
197188 </datatable-scroller>
189+ @if (summaryRow && summaryPosition === 'bottom') {
190+ <datatable-summary-row
191+ role="row"
192+ [rowHeight]="summaryHeight"
193+ [innerWidth]="innerWidth"
194+ [rows]="rows"
195+ [columns]="columns"
196+ >
197+ </datatable-summary-row>
198+ }
198199 }
199200 @if (!rows?.length && !loadingIndicator && !ghostLoadingIndicator) {
200201 <datatable-scroller
@@ -219,7 +220,6 @@ import { Keys } from '../../utils/keys';
219220 ScrollerComponent ,
220221 DataTableSummaryRowComponent ,
221222 DataTableRowWrapperComponent ,
222- NgStyle ,
223223 DatatableRowDefInternalDirective ,
224224 DataTableBodyRowComponent ,
225225 DraggableDirective ,
@@ -650,77 +650,18 @@ export class DataTableBodyComponent<TRow extends Row = any> implements OnInit, O
650650 } ;
651651
652652 /**
653- * Calculates the styles for the row so that the rows can be moved in 2D space
654- * during virtual scroll inside the DOM. In the below case the Y position is
655- * manipulated. As an example, if the height of row 0 is 30 px and row 1 is
656- * 100 px then following styles are generated:
657- *
658- * transform: translate3d(0px, 0px, 0px); -> row0
659- * transform: translate3d(0px, 30px, 0px); -> row1
660- * transform: translate3d(0px, 130px, 0px); -> row2
661- *
662- * Row heights have to be calculated based on the row heights cache as we wont
663- * be able to determine which row is of what height before hand. In the above
664- * case the positionY of the translate3d for row2 would be the sum of all the
665- * heights of the rows before it (i.e. row0 and row1).
666- *
667- * @returns the CSS3 style to be applied
668- */
669- rowsStyles = computed ( ( ) => {
670- const rowsStyles : NgStyle [ 'ngStyle' ] [ ] = [ ] ;
671- this . rowsToRender ( ) . forEach ( ( rows , index ) => {
672- const styles : NgStyle [ 'ngStyle' ] = { } ;
673-
674- // only add styles for the group if there is a group
675- if ( this . groupedRows ) {
676- styles . width = this . columnGroupWidths . total ;
677- }
678-
679- if ( this . scrollbarV && this . virtualization ) {
680- let idx = 0 ;
681-
682- if ( Array . isArray ( rows ) ) {
683- // Get the latest row rowindex in a group
684- const row = rows [ rows . length - 1 ] ;
685- // The group row, which has always a numeric index
686- idx = row ? this . getRowIndex ( row ) . index : 0 ;
687- } else {
688- if ( rows ) {
689- // normal rows always have a numeric index
690- idx = this . getRowIndex ( rows ) . index ;
691- } else {
692- // When ghost cells are enabled use index to get the position of them
693- idx = this . indexes ( ) . first + index ;
694- }
695- }
696-
697- // const pos = idx * rowHeight;
698- // The position of this row would be the sum of all row heights
699- // until the previous row position.
700- styles . transform = `translateY(${ this . rowHeightsCache ( ) . query ( idx - 1 ) } px)` ;
701- }
702- rowsStyles . push ( styles ) ;
703- } ) ;
704- return rowsStyles ;
705- } ) ;
706-
707- /**
708- * Calculate bottom summary row offset for scrollbar mode.
709- * For more information about cache and offset calculation
710- * see description for `rowsStyles` signal
711- *
712- * @returns the CSS3 style to be applied
653+ * Calculates the offset of the rendered rows.
654+ * As virtual rows are not shown, we have to move all rendered rows
655+ * by the total size of previous non-rendered rows.
656+ * If each row has a size of 10px and the first 10 rows are not rendered due to scroll,
657+ * then we have a renderOffset of 100px.
713658 */
714- bottomSummaryRowsStyles = computed ( ( ) => {
715- if ( ! this . scrollbarV || ! this . rows . length || ! this . rowsToRender ( ) ) {
716- return null ;
659+ renderOffset = computed ( ( ) => {
660+ if ( this . scrollbarV && this . virtualization ) {
661+ return `translateY(${ this . rowHeightsCache ( ) . query ( this . indexes ( ) . first - 1 ) } px)` ;
662+ } else {
663+ return '' ;
717664 }
718-
719- const pos = this . rowHeightsCache ( ) . query ( this . rows . length - 1 ) ;
720- return {
721- transform : `translateY(${ pos } px)` ,
722- position : 'absolute'
723- } ;
724665 } ) ;
725666
726667 /**
0 commit comments