diff --git a/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts b/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts index 6f9742c..e30da90 100644 --- a/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts +++ b/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts @@ -8,6 +8,7 @@ import { ElementRef, OnDestroy, AfterViewInit, + NgZone, } from '@angular/core'; import { OverlayScrollbars } from 'overlayscrollbars'; import type { PartialOptions, EventListeners, EventListenerArgs } from 'overlayscrollbars'; @@ -55,7 +56,7 @@ export class OverlayScrollbarsComponent implements OnDestroy, AfterViewInit { @ViewChild('content', { read: OverlayScrollbarsDirective }) private osDirective?: OverlayScrollbarsDirective; - constructor(private targetRef: ElementRef) {} + constructor(private ngZone: NgZone, private targetRef: ElementRef) {} osInstance(): OverlayScrollbars | null { return this.osDirective!.osInstance(); @@ -88,12 +89,24 @@ export class OverlayScrollbarsComponent implements OnDestroy, AfterViewInit { mergeEvents(originalEvents: OverlayScrollbarsComponent['events']) { return mergeEventListeners( { - initialized: (...args) => this.onInitialized.emit(args), - updated: (...args) => this.onUpdated.emit(args), - destroyed: (...args) => this.onDestroyed.emit(args), - scroll: (...args) => this.onScroll.emit(args), + initialized: (...args) => this.dispatchEventIfHasObservers(this.onInitialized, args), + updated: (...args) => this.dispatchEventIfHasObservers(this.onUpdated, args), + destroyed: (...args) => this.dispatchEventIfHasObservers(this.onDestroyed, args), + scroll: (...args) => this.dispatchEventIfHasObservers(this.onScroll, args), }, originalEvents || {} ); } + + private dispatchEventIfHasObservers(eventEmitter: EventEmitter, args: T): void { + // `observed` is available since RxJS@7.2 because `observers` is being deprecated. + if ((eventEmitter as any).observed || eventEmitter.observers.length > 0) { + // This is required to re-enter the Angular zone to call the event handler in the Angular + // zone too. This will not re-enter the Angular zone if emitter doesn't have any observers, + // for instance, it's being listened: `` zone, see `OverlayScrollbarsDirective#osInitialize`. + this.ngZone.run(() => eventEmitter.emit(args)); + } + } }