11import { NgForOfContext } from '@angular/common' ;
2- import { ChangeDetectorRef , ComponentRef , Directive , DoCheck , EmbeddedViewRef , EventEmitter , Input , IterableChanges , IterableDiffer , IterableDiffers , NgZone , OnChanges , OnDestroy , OnInit , Output , SimpleChanges , TemplateRef , TrackByFunction , ViewContainerRef , AfterViewInit , booleanAttribute , DOCUMENT , inject } from '@angular/core' ;
2+ import { ChangeDetectorRef , ComponentRef , Directive , EmbeddedViewRef , EventEmitter , Input , IterableChanges , IterableDiffer , IterableDiffers , NgZone , OnChanges , OnDestroy , OnInit , Output , SimpleChanges , TemplateRef , TrackByFunction , ViewContainerRef , AfterViewInit , booleanAttribute , DOCUMENT , inject , afterNextRender , runInInjectionContext , EnvironmentInjector } from '@angular/core' ;
33
44import { DisplayContainerComponent } from './display.container' ;
55import { HVirtualHelperComponent } from './horizontal.virtual.helper.component' ;
@@ -84,16 +84,17 @@ export abstract class IgxForOfToken<T, U extends T[] = T[]> {
8484 ] ,
8585 standalone : true
8686} )
87- export class IgxForOfDirective < T , U extends T [ ] = T [ ] > extends IgxForOfToken < T , U > implements OnInit , OnChanges , DoCheck , OnDestroy , AfterViewInit {
87+ export class IgxForOfDirective < T , U extends T [ ] = T [ ] > extends IgxForOfToken < T , U > implements OnInit , OnChanges , OnDestroy , AfterViewInit {
8888 private _viewContainer = inject ( ViewContainerRef ) ;
8989 protected _template = inject < TemplateRef < NgForOfContext < T > > > ( TemplateRef ) ;
9090 protected _differs = inject ( IterableDiffers ) ;
91+ protected _injector = inject ( EnvironmentInjector ) ;
9192 public cdr = inject ( ChangeDetectorRef ) ;
9293 protected _zone = inject ( NgZone ) ;
9394 protected syncScrollService = inject ( IgxForOfScrollSyncService ) ;
9495 protected platformUtil = inject ( PlatformUtil ) ;
9596 protected document = inject ( DOCUMENT ) ;
96-
97+ private _igxForOf : U & T [ ] | null = null ;
9798
9899 /**
99100 * Sets the data to be rendered.
@@ -102,7 +103,16 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
102103 * ```
103104 */
104105 @Input ( )
105- public igxForOf : U & T [ ] | null ;
106+ public get igxForOf ( ) : U & T [ ] | null {
107+ return this . _igxForOf ;
108+ }
109+
110+ public set igxForOf ( value : U & T [ ] | null ) {
111+ this . _igxForOf = value ;
112+ if ( this . _differ ) {
113+ this . resolveDataDiff ( ) ;
114+ }
115+ }
106116
107117 /**
108118 * Sets the property name from which to read the size in the data object.
@@ -444,7 +454,7 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
444454 }
445455 this . _maxSize = this . _calcMaxBrowserSize ( ) ;
446456 if ( this . igxForScrollOrientation === 'vertical' ) {
447- this . dc . instance . _viewContainer . element . nativeElement . style . top = ' 0px' ;
457+ this . dc . instance . _viewContainer . element . nativeElement . style . transform = `translateY( 0px)` ;
448458 this . scrollComponent = this . syncScrollService . getScrollMaster ( this . igxForScrollOrientation ) ;
449459 if ( ! this . scrollComponent || this . scrollComponent . destroyed ) {
450460 this . scrollComponent = vc . createComponent ( VirtualHelperComponent ) . instance ;
@@ -484,6 +494,8 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
484494 }
485495 this . _updateScrollOffset ( ) ;
486496 }
497+ this . _differ = this . _differs . find ( this . igxForOf || [ ] ) . create ( this . igxForTrackBy ) ;
498+ this . resolveDataDiff ( ) ;
487499 }
488500
489501 public ngAfterViewInit ( ) : void {
@@ -555,7 +567,7 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
555567 /**
556568 * @hidden
557569 */
558- public ngDoCheck ( ) : void {
570+ public resolveDataDiff ( ) : void {
559571 if ( this . _differ ) {
560572 const changes = this . _differ . diff ( this . igxForOf ) ;
561573 if ( changes ) {
@@ -618,7 +630,13 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
618630 // Actual scroll delta that was added is smaller than 1 and onScroll handler doesn't trigger when scrolling < 1px
619631 const scrollOffset = this . fixedUpdateAllElements ( this . _virtScrollPosition ) ;
620632 // scrollOffset = scrollOffset !== parseInt(this.igxForItemSize, 10) ? scrollOffset : 0;
621- this . dc . instance . _viewContainer . element . nativeElement . style . top = - ( scrollOffset ) + 'px' ;
633+ runInInjectionContext ( this . _injector , ( ) => {
634+ afterNextRender ( {
635+ write : ( ) => {
636+ this . dc . instance . _viewContainer . element . nativeElement . style . transform = `translateY(${ - scrollOffset } px)` ;
637+ }
638+ } ) ;
639+ } ) ;
622640 }
623641
624642 const maxRealScrollTop = this . scrollComponent . nativeElement . scrollHeight - containerSize ;
@@ -903,15 +921,22 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
903921 if ( ! parseInt ( this . scrollComponent . nativeElement . style . height , 10 ) ) {
904922 return ;
905923 }
924+ this . scrollComponent . scrollAmount = event . target . scrollTop ;
906925 if ( ! this . _bScrollInternal ) {
907- this . _calcVirtualScrollPosition ( event . target . scrollTop ) ;
926+ this . _calcVirtualScrollPosition ( this . scrollComponent . scrollAmount ) ;
908927 } else {
909928 this . _bScrollInternal = false ;
910929 }
911930 const prevStartIndex = this . state . startIndex ;
912931 const scrollOffset = this . fixedUpdateAllElements ( this . _virtScrollPosition ) ;
913932
914- this . dc . instance . _viewContainer . element . nativeElement . style . top = - ( scrollOffset ) + 'px' ;
933+ runInInjectionContext ( this . _injector , ( ) => {
934+ afterNextRender ( {
935+ write : ( ) => {
936+ this . dc . instance . _viewContainer . element . nativeElement . style . transform = `translateY(${ - scrollOffset } px)` ;
937+ }
938+ } ) ;
939+ } ) ;
915940
916941 this . _zone . onStable . pipe ( first ( ) ) . subscribe ( this . recalcUpdateSizes . bind ( this ) ) ;
917942
@@ -1091,13 +1116,14 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
10911116 if ( ! parseInt ( firstScrollChild . style . width , 10 ) ) {
10921117 return ;
10931118 }
1119+ this . scrollComponent . scrollAmount = event . target . scrollLeft ;
10941120 if ( ! this . _bScrollInternal ) {
1095- this . _calcVirtualScrollPosition ( event . target . scrollLeft ) ;
1121+ this . _calcVirtualScrollPosition ( this . scrollComponent . scrollAmount ) ;
10961122 } else {
10971123 this . _bScrollInternal = false ;
10981124 }
10991125 const prevStartIndex = this . state . startIndex ;
1100- const scrLeft = event . target . scrollLeft ;
1126+ const scrLeft = this . scrollComponent . scrollAmount ;
11011127 // Updating horizontal chunks
11021128 const scrollOffset = this . fixedUpdateAllElements ( Math . abs ( this . _virtScrollPosition ) ) ;
11031129 if ( scrLeft < 0 ) {
@@ -1463,8 +1489,10 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
14631489 const scroll = this . scrollComponent . nativeElement ;
14641490 scrollOffset = scroll && this . scrollComponent . size ?
14651491 currentScroll - this . sizesCache [ this . state . startIndex ] : 0 ;
1466- const dir = this . igxForScrollOrientation === 'horizontal' ? 'left' : 'top' ;
1467- this . dc . instance . _viewContainer . element . nativeElement . style [ dir ] = - ( scrollOffset ) + 'px' ;
1492+ const dir = this . igxForScrollOrientation === 'horizontal' ? 'left' : 'transform' ;
1493+ this . dc . instance . _viewContainer . element . nativeElement . style [ dir ] = this . igxForScrollOrientation === 'horizontal' ?
1494+ - ( scrollOffset ) + 'px' :
1495+ `translateY(${ - scrollOffset } px)` ;
14681496 }
14691497
14701498 protected _adjustScrollPositionAfterSizeChange ( sizeDiff ) {
@@ -1474,7 +1502,7 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
14741502 this . recalcUpdateSizes ( ) ;
14751503 const offset = this . igxForScrollOrientation === 'horizontal' ?
14761504 parseInt ( this . dc . instance . _viewContainer . element . nativeElement . style . left , 10 ) :
1477- parseInt ( this . dc . instance . _viewContainer . element . nativeElement . style . top , 10 ) ;
1505+ Number ( this . dc . instance . _viewContainer . element . nativeElement . style . transform ?. match ( / t r a n s l a t e Y \( ( - ? \d + \. ? \d * ) p x \) / ) ?. [ 1 ] ) ;
14781506 const newSize = this . sizesCache [ this . state . startIndex ] - offset ;
14791507 this . scrollPosition = newSize ;
14801508 if ( this . scrollPosition !== newSize ) {
@@ -1526,7 +1554,7 @@ export class IgxGridForOfContext<T, U extends T[] = T[]> extends IgxForOfContext
15261554 selector : '[igxGridFor][igxGridForOf]' ,
15271555 standalone : true
15281556} )
1529- export class IgxGridForOfDirective < T , U extends T [ ] = T [ ] > extends IgxForOfDirective < T , U > implements OnInit , OnChanges , DoCheck {
1557+ export class IgxGridForOfDirective < T , U extends T [ ] = T [ ] > extends IgxForOfDirective < T , U > implements OnInit , OnChanges {
15301558 protected syncService = inject ( IgxForOfSyncService ) ;
15311559
15321560 @Input ( )
@@ -1643,7 +1671,7 @@ export class IgxGridForOfDirective<T, U extends T[] = T[]> extends IgxForOfDirec
16431671 this . syncService . setMaster ( this , true ) ;
16441672 }
16451673
1646- public override ngDoCheck ( ) {
1674+ public override resolveDataDiff ( ) {
16471675 if ( this . _differ ) {
16481676 const changes = this . _differ . diff ( this . igxForOf ) ;
16491677 if ( changes ) {
@@ -1677,19 +1705,25 @@ export class IgxGridForOfDirective<T, U extends T[] = T[]> extends IgxForOfDirec
16771705 }
16781706
16791707 public override onScroll ( event ) {
1680- if ( ! parseInt ( this . scrollComponent . nativeElement . style . height , 10 ) ) {
1708+ this . scrollComponent . scrollAmount = event . target . scrollTop ;
1709+ if ( ! this . scrollComponent . size ) {
16811710 return ;
16821711 }
16831712 if ( ! this . _bScrollInternal ) {
1684- this . _calcVirtualScrollPosition ( event . target . scrollTop ) ;
1713+ this . _calcVirtualScrollPosition ( this . scrollComponent . scrollAmount ) ;
16851714 } else {
16861715 this . _bScrollInternal = false ;
16871716 }
16881717 const scrollOffset = this . fixedUpdateAllElements ( this . _virtScrollPosition ) ;
1718+ runInInjectionContext ( this . _injector , ( ) => {
1719+ afterNextRender ( {
1720+ write : ( ) => {
1721+ this . dc . instance . _viewContainer . element . nativeElement . style . transform = `translateY(${ - scrollOffset } px)` ;
1722+ this . _zone . onStable . pipe ( first ( ) ) . subscribe ( this . recalcUpdateSizes . bind ( this ) ) ;
1723+ }
1724+ } ) ;
1725+ } ) ;
16891726
1690- this . dc . instance . _viewContainer . element . nativeElement . style . top = - ( scrollOffset ) + 'px' ;
1691-
1692- this . _zone . onStable . pipe ( first ( ) ) . subscribe ( this . recalcUpdateSizes . bind ( this ) ) ;
16931727 this . cdr . markForCheck ( ) ;
16941728 }
16951729
@@ -1699,6 +1733,7 @@ export class IgxGridForOfDirective<T, U extends T[] = T[]> extends IgxForOfDirec
16991733 if ( ! this . scrollComponent || ! parseInt ( firstScrollChild . style . width , 10 ) ) {
17001734 return ;
17011735 }
1736+ this . scrollComponent . scrollAmount = scrollAmount ;
17021737 // Updating horizontal chunks
17031738 const scrollOffset = this . fixedUpdateAllElements ( Math . abs ( scrollAmount ) ) ;
17041739 if ( scrollAmount < 0 ) {
0 commit comments