Skip to content

Commit 4acad9d

Browse files
committed
feat: add push pipe
1 parent 9fcc00b commit 4acad9d

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

libs/angular-three/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export * from './lib/utils/is';
1111
export * from './lib/loader';
1212
export * from './lib/di/ref';
1313
export * from './lib/di/destroy';
14+
export * from './lib/pipes/push';
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { ChangeDetectorRef, inject, OnDestroy, Pipe, PipeTransform } from '@angular/core';
2+
import { isObservable, ObservableInput, Subscription } from 'rxjs';
3+
4+
function isPromise(value: unknown): value is Promise<unknown> {
5+
return (
6+
(value instanceof Promise || Object.prototype.toString.call(value) === '[object Promise]') &&
7+
typeof (value as Promise<unknown>)['then'] === 'function'
8+
);
9+
}
10+
11+
@Pipe({ name: 'ngtPush', pure: false, standalone: true })
12+
export class NgtPush<T> implements PipeTransform, OnDestroy {
13+
private readonly cdr = inject(ChangeDetectorRef);
14+
private readonly parentCdr = inject(ChangeDetectorRef, { skipSelf: true, optional: true });
15+
16+
private sub?: Subscription;
17+
private obj?: ObservableInput<T>;
18+
private latestValue?: T;
19+
20+
transform(value: ObservableInput<T>, defaultValue: T = null!): T {
21+
if (this.obj === value) {
22+
return this.latestValue as T;
23+
}
24+
this.obj = value;
25+
this.latestValue = defaultValue;
26+
27+
if (this.sub) {
28+
this.sub.unsubscribe();
29+
}
30+
31+
if (isObservable(this.obj)) {
32+
this.sub = this.obj.subscribe(this.updateValue.bind(this));
33+
} else if (isPromise(this.obj)) {
34+
(this.obj as Promise<T>).then(this.updateValue.bind(this));
35+
} else {
36+
throw new Error(`[NGT] Invalid value passed to ngtPush pipe`);
37+
}
38+
39+
return this.latestValue as T;
40+
}
41+
42+
updateValue(val: T) {
43+
this.latestValue = val;
44+
this.cdr.detectChanges();
45+
if (this.parentCdr) {
46+
this.parentCdr.detectChanges();
47+
}
48+
}
49+
50+
ngOnDestroy() {
51+
if (this.sub) {
52+
this.sub.unsubscribe();
53+
}
54+
this.latestValue = undefined;
55+
this.obj = undefined;
56+
}
57+
}

0 commit comments

Comments
 (0)