diff --git a/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts b/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts
index d05d79d..8e2cad3 100644
--- a/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts
+++ b/packages/overlayscrollbars-ngx/src/overlayscrollbars.component.ts
@@ -7,12 +7,10 @@ import {
ViewChild,
ElementRef,
OnDestroy,
- OnChanges,
AfterViewInit,
- SimpleChanges,
- NgZone,
} from '@angular/core';
import { OverlayScrollbars } from 'overlayscrollbars';
+import { OverlayScrollbarsDirective } from '~/overlayscrollbars.directive';
import type { PartialOptions, EventListeners, EventListenerMap } from 'overlayscrollbars';
const mergeEventListeners = (emits: EventListeners, events: EventListeners) =>
@@ -31,17 +29,19 @@ const mergeEventListeners = (emits: EventListeners, events: EventListeners) =>
);
@Component({
- selector: '[overlay-scrollbars]', // https://angular.io/guide/styleguide#component-selectors
+ selector: '[overlay-scrollbars-component]', // https://angular.io/guide/styleguide#component-selectors
exportAs: 'overlayScrollbars',
host: { 'data-overlayscrollbars': '' },
- template: `
`,
+ template: `
+
+
`,
})
-export class OverlayScrollbarsComponent implements OnDestroy, OnChanges, AfterViewInit {
- private instanceRef: OverlayScrollbars | null = null;
-
- @ViewChild('content')
- private contentRef?: ElementRef;
-
+export class OverlayScrollbarsComponent implements OnDestroy, AfterViewInit {
@Input('options')
options?: PartialOptions | false | null;
@Input('events')
@@ -56,9 +56,42 @@ export class OverlayScrollbarsComponent implements OnDestroy, OnChanges, AfterVi
@Output('osScroll')
onScroll = new EventEmitter();
- constructor(private targetRef: ElementRef, private ngZone: NgZone) {}
+ @ViewChild('content')
+ private contentRef?: ElementRef;
+ @ViewChild('content', { read: OverlayScrollbarsDirective })
+ private osDirective?: OverlayScrollbarsDirective;
- private mergedEvents(originalEvents: OverlayScrollbarsComponent['events']) {
+ constructor(private targetRef: ElementRef) {}
+
+ instance(): OverlayScrollbars | null {
+ return this.osDirective!.instance();
+ }
+
+ element(): HTMLElement {
+ return this.targetRef.nativeElement;
+ }
+
+ ngAfterViewInit() {
+ const targetElm = this.element();
+ const contentElm = this.contentRef!.nativeElement;
+
+ /* istanbul ignore else */
+ if (targetElm && contentElm) {
+ this.osDirective!.initialize({
+ target: targetElm,
+ elements: {
+ viewport: contentElm,
+ content: contentElm,
+ },
+ });
+ }
+ }
+
+ ngOnDestroy() {
+ this.osDirective?.instance()!.destroy();
+ }
+
+ private mergeEvents(originalEvents: OverlayScrollbarsComponent['events']) {
return mergeEventListeners(
{
initialized: (...args) => this.onInitialized.emit(args),
@@ -69,52 +102,4 @@ export class OverlayScrollbarsComponent implements OnDestroy, OnChanges, AfterVi
originalEvents || {}
);
}
-
- instance(): OverlayScrollbars | null {
- return this.instanceRef;
- }
-
- element(): HTMLElement {
- return this.targetRef.nativeElement;
- }
-
- ngAfterViewInit() {
- this.ngZone.runOutsideAngular(() => {
- const targetElm = this.element();
- const contentElm = this.contentRef!.nativeElement;
-
- /* istanbul ignore else */
- if (targetElm && contentElm) {
- this.instanceRef = OverlayScrollbars(
- {
- target: targetElm,
- elements: {
- viewport: contentElm,
- content: contentElm,
- },
- },
- this.options || {},
- this.mergedEvents(this.events)
- );
- }
- });
- }
-
- ngOnDestroy() {
- this.instanceRef?.destroy();
- }
-
- ngOnChanges(changes: SimpleChanges) {
- const optionsChange = changes.options;
- const eventsChange = changes.events;
-
- if (OverlayScrollbars.valid(this.instanceRef)) {
- if (optionsChange) {
- this.instanceRef.options(optionsChange.currentValue || {}, true);
- }
- if (eventsChange) {
- this.instanceRef.on(this.mergedEvents(eventsChange.currentValue), true);
- }
- }
- }
}
diff --git a/packages/overlayscrollbars-ngx/src/overlayscrollbars.directive.ts b/packages/overlayscrollbars-ngx/src/overlayscrollbars.directive.ts
new file mode 100644
index 0000000..c8ed30e
--- /dev/null
+++ b/packages/overlayscrollbars-ngx/src/overlayscrollbars.directive.ts
@@ -0,0 +1,65 @@
+/* eslint-disable @typescript-eslint/consistent-type-imports */
+import { Directive, Input, OnChanges, SimpleChanges, NgZone } from '@angular/core';
+import { OverlayScrollbars } from 'overlayscrollbars';
+import type { InitializationTarget } from 'overlayscrollbars';
+import type { OverlayScrollbarsComponent } from '~/overlayscrollbars.component';
+
+@Directive({
+ selector: '[overlayScrollbarsDirective]', // https://angular.io/guide/styleguide#component-selectors
+ exportAs: 'overlayScrollbars',
+})
+export class OverlayScrollbarsDirective implements OnChanges {
+ private instanceRef: OverlayScrollbars | null = null;
+
+ @Input('options')
+ options?: OverlayScrollbarsComponent['options'];
+ @Input('events')
+ events?: OverlayScrollbarsComponent['events'];
+
+ constructor(private ngZone: NgZone) {}
+
+ initialize(target: InitializationTarget): OverlayScrollbars {
+ this.ngZone.runOutsideAngular(() => {
+ this.instanceRef = OverlayScrollbars(
+ target,
+ this.options || {},
+ /* istanbul ignore next */
+ this.events || {}
+ );
+ });
+ return this.instanceRef!;
+ }
+
+ instance(): OverlayScrollbars | null {
+ return this.instanceRef;
+ }
+
+ ngOnChanges(changes: SimpleChanges) {
+ const optionsChange = changes.options;
+ const eventsChange = changes.events;
+
+ if (optionsChange) {
+ const curr = optionsChange.currentValue;
+
+ this.options = curr;
+
+ if (OverlayScrollbars.valid(this.instanceRef)) {
+ this.instanceRef.options(curr || {}, true);
+ }
+ }
+ /* istanbul ignore else */
+ if (eventsChange) {
+ const curr = eventsChange.currentValue;
+
+ this.events = curr;
+
+ if (OverlayScrollbars.valid(this.instanceRef)) {
+ this.instanceRef.on(
+ /* istanbul ignore next */
+ curr || {},
+ true
+ );
+ }
+ }
+ }
+}
diff --git a/packages/overlayscrollbars-ngx/src/overlayscrollbars.module.ts b/packages/overlayscrollbars-ngx/src/overlayscrollbars.module.ts
index 2b86978..e9a20aa 100644
--- a/packages/overlayscrollbars-ngx/src/overlayscrollbars.module.ts
+++ b/packages/overlayscrollbars-ngx/src/overlayscrollbars.module.ts
@@ -1,8 +1,9 @@
import { NgModule } from '@angular/core';
+import { OverlayScrollbarsDirective } from './overlayscrollbars.directive';
import { OverlayScrollbarsComponent } from './overlayscrollbars.component';
@NgModule({
- declarations: [OverlayScrollbarsComponent],
- exports: [OverlayScrollbarsComponent],
+ declarations: [OverlayScrollbarsComponent, OverlayScrollbarsDirective],
+ exports: [OverlayScrollbarsComponent, OverlayScrollbarsDirective],
})
export class OverlayscrollbarsModule {}
diff --git a/packages/overlayscrollbars-ngx/src/public-api.ts b/packages/overlayscrollbars-ngx/src/public-api.ts
index 4657260..735197d 100644
--- a/packages/overlayscrollbars-ngx/src/public-api.ts
+++ b/packages/overlayscrollbars-ngx/src/public-api.ts
@@ -1,2 +1,3 @@
export * from './overlayscrollbars.component';
+export * from './overlayscrollbars.directive';
export * from './overlayscrollbars.module';
diff --git a/packages/overlayscrollbars-ngx/test/overlayscrollbars.component.spec.ts b/packages/overlayscrollbars-ngx/test/overlayscrollbars.component.spec.ts
index 0e2bf05..9f70eee 100644
--- a/packages/overlayscrollbars-ngx/test/overlayscrollbars.component.spec.ts
+++ b/packages/overlayscrollbars-ngx/test/overlayscrollbars.component.spec.ts
@@ -1,14 +1,18 @@
import { Component, ViewChild } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { OverlayScrollbars } from 'overlayscrollbars';
-import { OverlayScrollbarsComponent, OverlayscrollbarsModule } from '~/public-api';
+import {
+ OverlayScrollbarsComponent,
+ OverlayScrollbarsDirective,
+ OverlayscrollbarsModule,
+} from '~/public-api';
import type { ComponentFixture } from '@angular/core/testing';
import type { EventListenerMap } from 'overlayscrollbars';
@Component({
template: `
hello
angular
empty
@@ -73,7 +77,7 @@ describe('OverlayscrollbarsNgxComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
...new OverlayscrollbarsModule(),
- declarations: [OverlayScrollbarsComponent, Test],
+ declarations: [OverlayScrollbarsComponent, OverlayScrollbarsDirective, Test],
}).compileComponents();
fixture = TestBed.createComponent(OverlayScrollbarsComponent);