Skip to content

Commit 25875b1

Browse files
committed
fixup! feat(cdk/scrolling): make scroller element configurable for virtual scrolling
1 parent 3bfb3fe commit 25875b1

File tree

6 files changed

+53
-20
lines changed

6 files changed

+53
-20
lines changed

src/cdk/scrolling/scrollable.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,11 @@ export type ExtendedScrollToOptions = _XAxis & _YAxis & ScrollOptions;
4545
selector: '[cdk-scrollable], [cdkScrollable]',
4646
})
4747
export class CdkScrollable implements OnInit, OnDestroy {
48-
private readonly _destroyed = new Subject<void>();
48+
protected readonly _destroyed = new Subject<void>();
4949

50-
private _elementScrolled: Observable<Event> = new Observable((observer: Observer<Event>) =>
50+
protected _elementScrolled: Observable<Event> = new Observable((observer: Observer<Event>) =>
5151
this.ngZone.runOutsideAngular(() =>
52-
/* it seems like scroll-events are not fired on the documentElement, event if it's the actual scrolling element */
53-
fromEvent(
54-
this.elementRef.nativeElement === document.documentElement
55-
? document
56-
: this.elementRef.nativeElement,
57-
'scroll',
58-
)
52+
fromEvent(this.elementRef.nativeElement, 'scroll')
5953
.pipe(takeUntil(this._destroyed))
6054
.subscribe(observer),
6155
),

src/cdk/scrolling/virtual-scroll-viewport.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {
2020
OnInit,
2121
Optional,
2222
Output,
23-
Renderer2,
2423
ViewChild,
2524
ViewEncapsulation,
2625
} from '@angular/core';
@@ -69,8 +68,11 @@ const SCROLL_SCHEDULER =
6968
providers: [
7069
{
7170
provide: CdkScrollable,
72-
useFactory: (scrollViewport: CdkVirtualScrollViewport) => scrollViewport.scrollable,
73-
deps: [CdkVirtualScrollViewport],
71+
useFactory: (
72+
virtualScrollable: CdkVirtualScrollable | null,
73+
viewport: CdkVirtualScrollViewport,
74+
) => virtualScrollable || viewport,
75+
deps: [CdkVirtualScrollable, CdkVirtualScrollViewport],
7476
},
7577
],
7678
})
@@ -86,6 +88,7 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
8688
get orientation() {
8789
return this._orientation;
8890
}
91+
8992
set orientation(orientation: 'horizontal' | 'vertical') {
9093
if (this._orientation !== orientation) {
9194
this._orientation = orientation;
@@ -182,7 +185,6 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
182185
@Optional() dir: Directionality,
183186
scrollDispatcher: ScrollDispatcher,
184187
viewportRuler: ViewportRuler,
185-
renderer: Renderer2,
186188
@Optional() @Inject(VIRTUAL_SCROLLABLE) public scrollable: CdkVirtualScrollable,
187189
) {
188190
super(elementRef, scrollDispatcher, ngZone, dir);
@@ -197,7 +199,7 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
197199

198200
if (!this.scrollable) {
199201
// No scrollable is provided, so the virtual-scroll-viewport needs to become a scrollable
200-
renderer.addClass(this.elementRef.nativeElement, 'cdk-virtual-scrollable');
202+
this.elementRef.nativeElement.classList.add('cdk-virtual-scrollable');
201203
this.scrollable = this;
202204
}
203205
}
@@ -292,6 +294,10 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
292294
return this._renderedRange;
293295
}
294296

297+
getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number {
298+
return this.getElementRef().nativeElement.getBoundingClientRect()[from];
299+
}
300+
295301
/**
296302
* Sets the total size of all content (in pixels), including content that is not currently
297303
* rendered.
@@ -423,9 +429,7 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
423429
fromRect = this.orientation === 'horizontal' ? 'left' : 'top';
424430
}
425431

426-
const scrollerClientRect = this.scrollable
427-
.getElementRef()
428-
.nativeElement.getBoundingClientRect()[fromRect];
432+
const scrollerClientRect = this.scrollable.getBoundingClientRectWithScrollOffset(fromRect);
429433
const viewportClientRect = this.elementRef.nativeElement.getBoundingClientRect()[fromRect];
430434

431435
return viewportClientRect - scrollerClientRect;

src/cdk/scrolling/virtual-scrollable-element.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ export class CdkVirtualScrollableElement extends CdkVirtualScrollable {
2727
) {
2828
super(elementRef, scrollDispatcher, ngZone, dir);
2929
}
30+
31+
getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number {
32+
return (
33+
this.getElementRef().nativeElement.getBoundingClientRect()[from] -
34+
this.measureScrollOffset(from)
35+
);
36+
}
3037
}

src/cdk/scrolling/virtual-scrollable-window.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import {Directionality} from '@angular/cdk/bidi';
1010
import {Directive, ElementRef, NgZone, Optional} from '@angular/core';
11+
import {fromEvent, Observable, Observer} from 'rxjs';
12+
import {takeUntil} from 'rxjs/operators';
1113
import {ScrollDispatcher} from './scroll-dispatcher';
1214
import {CdkVirtualScrollable, VIRTUAL_SCROLLABLE} from './virtual-scrollable';
1315

@@ -16,7 +18,18 @@ import {CdkVirtualScrollable, VIRTUAL_SCROLLABLE} from './virtual-scrollable';
1618
providers: [{provide: VIRTUAL_SCROLLABLE, useExisting: CdkVirtualScrollableWindow}],
1719
})
1820
export class CdkVirtualScrollableWindow extends CdkVirtualScrollable {
21+
protected override _elementScrolled: Observable<Event> = new Observable(
22+
(observer: Observer<Event>) =>
23+
this.ngZone.runOutsideAngular(() =>
24+
fromEvent(document, 'scroll').pipe(takeUntil(this._destroyed)).subscribe(observer),
25+
),
26+
);
27+
1928
constructor(scrollDispatcher: ScrollDispatcher, ngZone: NgZone, @Optional() dir: Directionality) {
2029
super(new ElementRef(document.documentElement), scrollDispatcher, ngZone, dir);
2130
}
31+
32+
getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number {
33+
return this.getElementRef().nativeElement.getBoundingClientRect()[from];
34+
}
2235
}

src/cdk/scrolling/virtual-scrollable.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ export abstract class CdkVirtualScrollable extends CdkScrollable {
2828
const viewportEl = this.elementRef.nativeElement;
2929
return orientation === 'horizontal' ? viewportEl.clientWidth : viewportEl.clientHeight;
3030
}
31+
32+
abstract getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number;
3133
}

tools/public_api_guard/cdk/scrolling.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import { OnDestroy } from '@angular/core';
2626
import { OnInit } from '@angular/core';
2727
import { Platform } from '@angular/cdk/platform';
2828
import { _RecycleViewRepeaterStrategy } from '@angular/cdk/collections';
29-
import { Renderer2 } from '@angular/core';
3029
import { Subject } from 'rxjs';
3130
import { Subscription } from 'rxjs';
3231
import { TemplateRef } from '@angular/core';
@@ -65,10 +64,14 @@ export class CdkFixedSizeVirtualScroll implements OnChanges {
6564
export class CdkScrollable implements OnInit, OnDestroy {
6665
constructor(elementRef: ElementRef<HTMLElement>, scrollDispatcher: ScrollDispatcher, ngZone: NgZone, dir?: Directionality | undefined);
6766
// (undocumented)
67+
protected readonly _destroyed: Subject<void>;
68+
// (undocumented)
6869
protected dir?: Directionality | undefined;
6970
// (undocumented)
7071
protected elementRef: ElementRef<HTMLElement>;
7172
elementScrolled(): Observable<Event>;
73+
// (undocumented)
74+
protected _elementScrolled: Observable<Event>;
7275
getElementRef(): ElementRef<HTMLElement>;
7376
measureScrollOffset(from: 'top' | 'left' | 'right' | 'bottom' | 'start' | 'end'): number;
7477
// (undocumented)
@@ -142,6 +145,8 @@ export type CdkVirtualForOfContext<T> = {
142145
export abstract class CdkVirtualScrollable extends CdkScrollable {
143146
constructor(elementRef: ElementRef<HTMLElement>, scrollDispatcher: ScrollDispatcher, ngZone: NgZone, dir?: Directionality);
144147
// (undocumented)
148+
abstract getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number;
149+
// (undocumented)
145150
measureViewportSize(orientation: 'horizontal' | 'vertical'): number;
146151
// (undocumented)
147152
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkVirtualScrollable, never, never, {}, {}, never>;
@@ -153,6 +158,8 @@ export abstract class CdkVirtualScrollable extends CdkScrollable {
153158
export class CdkVirtualScrollableElement extends CdkVirtualScrollable {
154159
constructor(elementRef: ElementRef, scrollDispatcher: ScrollDispatcher, ngZone: NgZone, dir: Directionality);
155160
// (undocumented)
161+
getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number;
162+
// (undocumented)
156163
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkVirtualScrollableElement, "[cdk-virtual-scrollable-element], [cdkVirtualScrollableElement]", never, {}, {}, never>;
157164
// (undocumented)
158165
static ɵfac: i0.ɵɵFactoryDeclaration<CdkVirtualScrollableElement, [null, null, null, { optional: true; }]>;
@@ -162,6 +169,10 @@ export class CdkVirtualScrollableElement extends CdkVirtualScrollable {
162169
export class CdkVirtualScrollableWindow extends CdkVirtualScrollable {
163170
constructor(scrollDispatcher: ScrollDispatcher, ngZone: NgZone, dir: Directionality);
164171
// (undocumented)
172+
protected _elementScrolled: Observable<Event>;
173+
// (undocumented)
174+
getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number;
175+
// (undocumented)
165176
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkVirtualScrollableWindow, "cdk-virtual-scroll-viewport[scrollable-window]", never, {}, {}, never>;
166177
// (undocumented)
167178
static ɵfac: i0.ɵɵFactoryDeclaration<CdkVirtualScrollableWindow, [null, null, { optional: true; }]>;
@@ -177,7 +188,7 @@ export interface CdkVirtualScrollRepeater<T> {
177188

178189
// @public
179190
export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements OnInit, OnDestroy {
180-
constructor(elementRef: ElementRef<HTMLElement>, _changeDetectorRef: ChangeDetectorRef, ngZone: NgZone, _scrollStrategy: VirtualScrollStrategy, dir: Directionality, scrollDispatcher: ScrollDispatcher, viewportRuler: ViewportRuler, renderer: Renderer2, scrollable: CdkVirtualScrollable);
191+
constructor(elementRef: ElementRef<HTMLElement>, _changeDetectorRef: ChangeDetectorRef, ngZone: NgZone, _scrollStrategy: VirtualScrollStrategy, dir: Directionality, scrollDispatcher: ScrollDispatcher, viewportRuler: ViewportRuler, scrollable: CdkVirtualScrollable);
181192
get appendOnly(): boolean;
182193
set appendOnly(value: BooleanInput);
183194
attach(forOf: CdkVirtualScrollRepeater<any>): void;
@@ -186,6 +197,8 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
186197
detach(): void;
187198
// (undocumented)
188199
elementRef: ElementRef<HTMLElement>;
200+
// (undocumented)
201+
getBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number;
189202
getDataLength(): number;
190203
getOffsetToRenderedContentStart(): number | null;
191204
getRenderedRange(): ListRange;
@@ -215,7 +228,7 @@ export class CdkVirtualScrollViewport extends CdkVirtualScrollable implements On
215228
// (undocumented)
216229
static ɵcmp: i0.ɵɵComponentDeclaration<CdkVirtualScrollViewport, "cdk-virtual-scroll-viewport", never, { "orientation": "orientation"; "appendOnly": "appendOnly"; }, { "scrolledIndexChange": "scrolledIndexChange"; }, never, ["*"]>;
217230
// (undocumented)
218-
static ɵfac: i0.ɵɵFactoryDeclaration<CdkVirtualScrollViewport, [null, null, null, { optional: true; }, { optional: true; }, null, null, null, { optional: true; }]>;
231+
static ɵfac: i0.ɵɵFactoryDeclaration<CdkVirtualScrollViewport, [null, null, null, { optional: true; }, { optional: true; }, null, null, { optional: true; }]>;
219232
}
220233

221234
// @public

0 commit comments

Comments
 (0)