Created
May 1, 2020 12:16
-
-
Save NyaGarcia/4aa6951c73fb9b0943e6cb0a192a3a28 to your computer and use it in GitHub Desktop.
Creando una directiva personalizada para renderizar Observables en el template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Directive, Input, TemplateRef, ViewContainerRef, | |
OnDestroy, OnInit, ChangeDetectorRef | |
} from '@angular/core' | |
import { Observable, Subject, AsyncSubject } from "rxjs"; | |
import { takeUntil, concatMapTo } from "rxjs/operators"; | |
export interface ObserveContext<T> { | |
$implicit: T; | |
observe: T; | |
} | |
export interface ErrorContext { | |
$implicit: Error; | |
} | |
@Directive({ | |
selector: "[observe]" | |
}) | |
export class ObserveDirective<T> implements OnDestroy, OnInit { | |
private errorRef: TemplateRef<ErrorContext>; | |
private beforeRef: TemplateRef<null>; | |
private unsubscribe = new Subject<boolean>(); | |
private init = new AsyncSubject<void>(); | |
constructor( | |
private view: ViewContainerRef, | |
private nextRef: TemplateRef<ObserveContext<T>>, | |
private changes: ChangeDetectorRef | |
) {} | |
@Input() | |
set observe(source: Observable<T>) { | |
if (!source) { | |
return | |
} | |
this.showBefore() | |
this.unsubscribe.next(true); | |
this.init.pipe( | |
concatMapTo(source), | |
takeUntil(this.unsubscribe) | |
).subscribe(value => { | |
this.view.clear() | |
this.view.createEmbeddedView(this.nextRef, {$implicit: value, observe: value}) | |
this.changes.markForCheck() | |
}, error => { | |
if (this.errorRef) { | |
this.view.clear() | |
this.view.createEmbeddedView(this.errorRef, {$implicit: error}) | |
this.changes.markForCheck() | |
} | |
}) | |
} | |
@Input() | |
set observeError(ref: TemplateRef<ErrorContext>) { | |
this.errorRef = ref; | |
} | |
@Input() | |
set observeBefore(ref: TemplateRef<null>) { | |
this.beforeRef = ref; | |
} | |
ngOnDestroy() { | |
this.unsubscribe.next(true) | |
} | |
ngOnInit() { | |
this.showBefore() | |
this.init.next() | |
this.init.complete() | |
} | |
private showBefore(): void { | |
if (this.beforeRef) { | |
this.view.clear() | |
this.view.createEmbeddedView(this.beforeRef) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment