Last active
May 10, 2021 07:20
-
-
Save Airblader/28a84533a9d1c46d4abb9a956aa93eef to your computer and use it in GitHub Desktop.
Typescript / Angular Decorator: DetectChangesOnChange
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
// Copyright 2018 Ingo Bürk | |
// Released under the MIT License (https://opensource.org/licenses/MIT) | |
// TODO: Is there a better way to get access to a ChangeDetectorRef from | |
// within the decorator? | |
/** | |
* Decorator for class methods which caches the returned value and, | |
* if the value has changed, triggers change detection. | |
* | |
* Requires the method to take a ChangeDetectorRef as the first argument, | |
* e.g.: | |
* | |
* ``` | |
* @Component({ selector: "app-person", … }) | |
* export class PersonComponent { | |
* constructor(private cdRef: ChangeDetectorRef) {} | |
* | |
* public get something() { | |
* return this._calculateSomething(this.cdRef); | |
* } | |
* | |
* @DetectChangesOnChange() | |
* private _calculateSomething(cdRef: ChangeDetectorRef) { | |
* // … | |
* } | |
* } | |
* ``` | |
* | |
* NOTE: This requires the cached function to take exactly one argument, | |
* which is a ChangeDetectorRef. | |
* | |
* NOTE: Use with caution. Generally speaking, you should not call functions | |
* from the template. If possible, watch for changes on the tracked | |
* object and update internal component state instead. | |
*/ | |
function DetectChangesOnChange() { | |
return function( | |
target: any, | |
propertyKey: string, | |
descriptor: TypedPropertyDescriptor<(cdRef: ChangeDetectorRef) => any> | |
) { | |
const memoizedName = `${propertyKey}__DetectChangesOnChange`; | |
const _original = descriptor.value; | |
descriptor.value = function (cdRef: ChangeDetectorRef) { | |
const result = _original.apply(this, [cdRef]); | |
const detectChanges = result !== this[memoizedName]; | |
this[memoizedName] = result; | |
if (detectChanges) { | |
cdRef.detectChanges(); | |
} | |
return result; | |
} | |
return descriptor; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment