UNPKG

property-watch-decorator

Version:
131 lines (107 loc) 3.46 kB
# Property Watch Decorator #### This package provides a `@OnChange` decorator that can be easily used to listen to changes of class properties. ##### I have a [talk at ng-conf 2019](https://www.youtube.com/watch?v=rVDMmlCRvkg&list=PLOETEcp3DkCpimylVKTDe968yNmNIajlR&index=22) about why this package is useful and how I implement this package. ### Install ```npm install property-watch-decorator``` ### Example 1 ```typescript class PersonComponent { // Parameter value is inferred as any // Parameter change is optional, and inferred as SimpleChange<any> @OnChange(function(value, change) { console.log(`name is changed from ${change.previousValue} to ${value}`); }) name: string; } ``` ### Example 2, use generics, better typing ```typescript class PersonComponent { // Parameter value is inferred as string // Parameter change is optional, and inferred as SimpleChange<string> @OnChange<string>(function(value, change) { console.log(`name is changed from ${change.previousValue} to ${value}`); }) name: string; } ``` ### Example 3, type `this` if you want to access other member of the class (just for better IDE integration) ```typescript class PersonComponent { @OnChange<string>(function(this: PersonComponent, value, change) { console.log(`name is changed from ${change.previousValue} to ${value}`); console.log(`At the moment, age is ${this.age}`) }) name: string; age: number; } ``` ### Example 4, using class method reference for onChange (No need to type `this` as in example 3) ```typescript class PersonComponent { @OnChange<string>('onNameChange') name: string; age: number; onNameChange(value, change) { console.log(`name is changed from ${change.previousValue} to ${value}`); console.log(`At the moment, age is ${this.age}`); } } ``` ### Important notes: #### PITFALL 1 Arrow function should be avoided as this would make the function lose context. In this case, `this` would NOT refer to class instance but `undefined` For example: it is WRONG to use this way ```typescript class MyComponent { @OnChange(value => { console.log(`property1 is changed to ${value}`); console.log(this.property1) // "this" would refer to undefined, cannot access "property1" of undefined }) property1: any; } ``` #### Correct way Change arrow function to es5 function: ```typescript class MyComponent { @OnChange(function(value) { console.log(`property1 is changed to ${value}`); console.log(this.property1) // "this" would refer to component instance }) property1: any; } ``` #### PITFALL 2 Callback function CANNOT be referred to class method, this would also cause `this` to be `undefined` For example: ```typescript class MyComponent { @OnChange(this.someFunction) // "this" would refer to undefined, cannot access "someFunction" of undefined property1: any; someFunction(value) { console.log(`property1 is changed to ${value}`); console.log(this.property1) } } ``` #### Correct way 1 ```typescript class MyComponent { @OnChange('someFunction') property1; someFunction(value) { console.log(`property1 is changed to ${value}`); } } ``` #### Correct way 2 ```typescript class MyComponent { @OnChange(someFunction) property1; } function someFunction(value) { console.log(`property1 is changed to ${value}`); } ```