diff --git a/src/app/components/virtualscroller/virtualscroller.spec.ts b/src/app/components/virtualscroller/virtualscroller.spec.ts new file mode 100644 index 00000000000..ff879d14776 --- /dev/null +++ b/src/app/components/virtualscroller/virtualscroller.spec.ts @@ -0,0 +1,46 @@ +import { ComponentRef } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { VirtualScroller, VirtualScrollerModule } from './virtualscroller'; + +describe('VirtualScroller', () => { + let virtualScroller: VirtualScroller; + let fixture: ComponentFixture; + let virtualScrollerRef: ComponentRef; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule, VirtualScrollerModule], + }); + + fixture = TestBed.createComponent(VirtualScroller); + virtualScroller = fixture.componentInstance; + virtualScrollerRef = fixture.componentRef; + }); + + it('should render the VirtualScroller with default inputs', () => { + fixture.detectChanges(); + + const virtualScrollerElement = fixture.nativeElement.querySelector('.p-virtualscroller'); + expect(virtualScrollerElement).toBeTruthy(); + }); + + it('should apply the correct style and styleClass', () => { + virtualScrollerRef.setInput('style', { 'max-height': '500px' }); + virtualScrollerRef.setInput('styleClass', 'custom-class'); + fixture.detectChanges(); + + const virtualScrollerElement = fixture.nativeElement.querySelector('.p-virtualscroller'); + expect(virtualScrollerElement.style.maxHeight).toBe('500px'); + expect(virtualScrollerElement.classList).toContain('custom-class'); + }); + + it('should scroll to the specified index', () => { + spyOn(virtualScroller.scroller(), 'scrollToIndex'); + + virtualScroller.scrollToIndex(10); + fixture.detectChanges(); + + expect(virtualScroller.scroller().scrollToIndex).toHaveBeenCalledWith(10, undefined); + }); +}); diff --git a/src/app/components/virtualscroller/virtualscroller.ts b/src/app/components/virtualscroller/virtualscroller.ts index 2e1beb1fe5f..324925ba423 100755 --- a/src/app/components/virtualscroller/virtualscroller.ts +++ b/src/app/components/virtualscroller/virtualscroller.ts @@ -1,22 +1,23 @@ -import { CommonModule } from '@angular/common'; +import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common'; import { - AfterContentInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, - ContentChild, - ContentChildren, + contentChild, + contentChildren, ElementRef, - EventEmitter, - Input, + OutputEmitterRef, + input, NgModule, - Output, - QueryList, + output, + Signal, TemplateRef, - ViewChild, + viewChild, ViewEncapsulation, booleanAttribute, numberAttribute, + computed, + inject, } from '@angular/core'; import { BlockableUI, Footer, Header, PrimeTemplate, ScrollerOptions, SharedModule } from 'primeng/api'; import { Scroller } from 'primeng/scroller'; @@ -31,31 +32,33 @@ import { VirtualScrollerLazyLoadEvent } from './virtualscroller.interface'; template: `
-
- - -
+ @if (header() || headerTemplate()) { +
+ + +
+ }
-
+
@@ -63,111 +66,93 @@ import { VirtualScrollerLazyLoadEvent } from './virtualscroller.interface';
- + @if (footer() || footerTemplate()) { + + }
`, changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, }) -export class VirtualScroller implements AfterContentInit, BlockableUI { +export class VirtualScroller implements BlockableUI { /** * An array of objects to display. * @group Props */ - @Input() value: any[] | undefined; + value = input(); /** * Height of an item in the list. * @group Props */ - @Input({ transform: numberAttribute }) itemSize: number | undefined; + itemSize = input(undefined, { transform: numberAttribute }); /** * Inline style of the component. * @group Props */ - @Input() style: { [klass: string]: any } | null | undefined; + style = input<{ [klass: string]: any } | null>(); /** * Style class of the component. * @group Props */ - @Input() styleClass: string | undefined; + styleClass = input(); /** * Max height of the content area in inline mode. * @group Props */ - @Input() scrollHeight: any; + scrollHeight = input(); /** * Defines if data is loaded and interacted with in lazy manner. * @group Props */ - @Input({ transform: booleanAttribute }) lazy: boolean | undefined; + lazy = input(undefined, { transform: booleanAttribute }); /** * Whether to use the scroller feature. The properties of scroller component can be used like an object in it. * @group Props */ - @Input() options: ScrollerOptions | undefined; + options = input(); /** * Threshold in milliseconds to delay lazy loading during scrolling. * @group Props */ - @Input({ transform: numberAttribute }) delay: number = 250; + delay = input(250, { transform: numberAttribute }); /** * Callback to invoke in lazy mode to load new data. * @param {VirtualScrollerLazyLoadEvent} event - custom lazy load event. * @group Emits */ - @Output() onLazyLoad: EventEmitter = new EventEmitter(); + onLazyLoad: OutputEmitterRef = output(); - @ContentChild(Header) header: Header | undefined; + header = contentChild
(Header); - @ContentChild(Footer) footer: Footer | undefined; + footer = contentChild