Last active
February 3, 2020 21:44
-
-
Save kaplan81/0683985b620f66bf7fbea6747a961c62 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 { Component, OnDestroy } from '@angular/core'; | |
import { Subject } from 'rxjs'; | |
// WARNING: THIS DECORATOR DOES NOT WORK IN ANGULAR 9 WITH IVY. | |
/** | |
* Method decorator to automatically unsubscribe in component classes. | |
* | |
* @example | |
* ```ts | |
* ngOnInit(): void { | |
* this.observable$.pipe(takeUntil((this as any).destroyed$)).subscribe(); | |
* } | |
* | |
* @ondestroy() | |
* ngOnDestroy(): void { | |
* // Optionally we can do anything we want here. | |
* } | |
* ``` | |
* | |
* Only 2 conditions: | |
* 1) `ngOnDestroy(): void {}` must be present in the component class. | |
* 2) We can only access `this.destroyed$` as `(this as any).destroyed$`. | |
*/ | |
export function ondestroy(): MethodDecorator { | |
/** | |
* This cannot be a symbol becase we need to access it | |
* in the component as `takeUntil((this as any).destroyed$)`. | |
* Otherwise we would have to export the symbol itslef | |
* and import it in the component class. | |
*/ | |
const destroyed$ = 'destroyed$'; | |
return (target: Component & OnDestroy, propertyKey: string, descriptor: PropertyDescriptor) => { | |
Object.defineProperty(target, destroyed$, { | |
// tslint:disable-next-line: rxjs-finnish | |
value: new Subject<void>(), | |
// This will prevent us from creating a new destroyed$ property in the component. | |
// It will throw an error if we try to do that. | |
writable: false, | |
enumerable: true, | |
configurable: true, | |
}); | |
const originalDescriptor = descriptor.value; | |
// This cannot be an arrow function | |
// So that we get the correct context of `this`. | |
descriptor.value = function() { | |
target[destroyed$].next(); | |
/** | |
* Normally you would pass the method arguments to the function: | |
* ```ts | |
* originalDescriptor.apply(this, arguments); | |
* ``` | |
* But ngOnDestroy() does not take any arguments. | |
*/ | |
originalDescriptor.apply(this); | |
}; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment