Skip to content

Commit

Permalink
feat(rx): create rxRenderInViewPort directive
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbe812 committed Jan 21, 2023
1 parent 95176f4 commit 86fcf51
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 157 deletions.
3 changes: 1 addition & 2 deletions libs/rx/platform/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ export * from './lib/create-mutation-observer';

export * from './lib/directives/rx-observe-resize.directive';
export * from './lib/directives/observe-intersection.directive';

export * from './lib/directives/rx-observe-visibility.directive';
export * from './lib/directives/observe-intersection.directive';
4 changes: 0 additions & 4 deletions libs/rx/platform/src/lib/directives/in-view.directive.spec.ts

This file was deleted.

151 changes: 0 additions & 151 deletions libs/rx/platform/src/lib/directives/in-view.directive.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// todo
describe('RxRenderInViewDirective', () => {

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
AfterViewInit,
Directive,
EmbeddedViewRef,
Input,
NgModule,
OnDestroy,
TemplateRef,
ViewContainerRef,
} from '@angular/core';
import {CommonModule} from '@angular/common';
import {combineLatest, mergeMap, SchedulerLike, startWith, Subscription} from 'rxjs';
import {createSignal} from '../../../../signal/src';
import {createIntersectionObserver} from '../create-intersection-observer';

@Directive({
selector: '[rxRenderInViewport]',
})
export class RxRenderInViewportDirective implements AfterViewInit, OnDestroy {
private alreadyRendered = false; // cheking if visible already
private embeddedViewRef: EmbeddedViewRef<unknown> | null = null;
private sub = new Subscription();

private rxObserveVisibilityDebounceSignal = createSignal(0);
private rxObserveVisibilityRootMarginSignal = createSignal('0px');
private rxObserveVisibilityRootSignal = createSignal<HTMLElement | undefined>(undefined);
private rxObserveVisibilityThresholdSignal = createSignal<number | number[]>(0);
private rxObserveVisibilitySchedulerSignal = createSignal<SchedulerLike | undefined>(undefined);

@Input() set rxRenderInViewport(rootMargin: string) {
this.rxObserveVisibilityRootMarginSignal.send(rootMargin);
}
@Input() set rxRenderInViewportDebounce(debounceInMs: number) {
this.rxObserveVisibilityDebounceSignal.send(debounceInMs);
}
@Input() set rxRenderInViewportRoot(root: HTMLElement | undefined) {
this.rxObserveVisibilityRootSignal.send(root);
}
@Input() set rxRenderInViewportThreshold(threshold: number | number[]) {
this.rxObserveVisibilityThresholdSignal.send(threshold);
}
@Input() set rxRenderInViewportScheduler(scheduler: SchedulerLike) {
this.rxObserveVisibilitySchedulerSignal.send(scheduler);
}

constructor(private vcRef: ViewContainerRef, private tplRef: TemplateRef<unknown>) {}

ngAfterViewInit() {
this.sub = combineLatest([
this.rxObserveVisibilityDebounceSignal.$.pipe(startWith(0)),
this.rxObserveVisibilityRootMarginSignal.$.pipe(startWith('0px')),
this.rxObserveVisibilityRootSignal.$.pipe(startWith(undefined)),
this.rxObserveVisibilityThresholdSignal.$.pipe(startWith(0)),
this.rxObserveVisibilitySchedulerSignal.$.pipe(startWith(undefined)),
])
.pipe(
mergeMap(([debounceInMs, rootMargin, root, threshold, scheduler]) =>
createIntersectionObserver(
this.vcRef.element.nativeElement.parentElement,
{
root: root,
rootMargin: rootMargin,
threshold: threshold,
},
{
throttleMs: debounceInMs,
scheduler: scheduler,
}
)
)
)
.subscribe((entries) => {
const entry = entries[0];
this.renderContents(entry.isIntersecting);
});
}

ngOnDestroy() {
this.embeddedViewRef?.destroy();
this.vcRef?.clear();
this.sub.unsubscribe();
}

renderContents(isInView: boolean) {
if (isInView && !this.alreadyRendered) {
this.vcRef.clear();
this.embeddedViewRef = this.vcRef.createEmbeddedView(this.tplRef);
this.embeddedViewRef.detectChanges();
this.alreadyRendered = true;
}
}
}

@NgModule({
imports: [CommonModule],
declarations: [RxRenderInViewportDirective],
exports: [RxRenderInViewportDirective],
})
export class RxRenderInViewportDirectiveModule {}

0 comments on commit 86fcf51

Please sign in to comment.