How to listen for value changes from class property TypeScript - Angular
You can still check component's field members value change by KeyValueDiffers
via DoCheck
lifehook.
import { DoCheck, KeyValueDiffers, KeyValueDiffer } from '@angular/core';differ: KeyValueDiffer<string, any>;constructor(private differs: KeyValueDiffers) { this.differ = this.differs.find({}).create();}ngDoCheck() { const change = this.differ.diff(this); if (change) { change.forEachChangedItem(item => { console.log('item changed', item); }); }}
see demo.
I think the nicest solution to your issue is to use a decorator that replaces the original field with a property automatically, then on the setter you can create a SimpleChanges
object similar to the one created by angular in order to use the same notification callback as for angular (alternatively you could create a different interface for these notifications, but the same principle applies)
import { OnChanges, SimpleChanges, DoCheck, SimpleChange } from '@angular/core';function Watch() : PropertyDecorator & MethodDecorator{ function isOnChanges(val: OnChanges): val is OnChanges{ return !!(val as OnChanges).ngOnChanges } return (target : any, key: string | symbol, propDesc?: PropertyDescriptor) => { let privateKey = "_" + key.toString(); let isNotFirstChangePrivateKey = "_" + key.toString() + 'IsNotFirstChange'; propDesc = propDesc || { configurable: true, enumerable: true, }; propDesc.get = propDesc.get || (function (this: any) { return this[privateKey] }); const originalSetter = propDesc.set || (function (this: any, val: any) { this[privateKey] = val }); propDesc.set = function (this: any, val: any) { let oldValue = this[key]; if(val != oldValue) { originalSetter.call(this, val); let isNotFirstChange = this[isNotFirstChangePrivateKey]; this[isNotFirstChangePrivateKey] = true; if(isOnChanges(this)) { var changes: SimpleChanges = { [key]: new SimpleChange(oldValue, val, !isNotFirstChange) } this.ngOnChanges(changes); } } } return propDesc; }}// Usageexport class MyClass implements OnChanges { //Properties what I want to track ! @Watch() myProperty_1: boolean = true @Watch() myProperty_2 = ['A', 'B', 'C']; @Watch() myProperty_3 = {}; constructor() { } ngOnChanges(changes: SimpleChanges) { console.log(changes); }}var myInatsnce = new MyClass(); // outputs original field setting with firstChange == truemyInatsnce.myProperty_2 = ["F"]; // will be notified on subsequent changes with firstChange == false
as said you can use
public set myProperty_2(value: type): void { if(value) { //doMyCheck } this._myProperty_2 = value;}
and then if you need to retrieve it
public get myProperty_2(): type { return this._myProperty_2;}
in that way you can do all the checks that you want while setting/ getting your variables such this methods will fire every time you set/get the myProperty_2 property.
small demo: https://stackblitz.com/edit/angular-n72qlu