Angular 12: how to detect changes of property in service

My existing project has some dependencies as below. I have one shared service class which holds one shared object "myObject". Lot of components are accessing this shared "SharedService"'s "myObject" and modifying the values.

Problem is that, each component is accessing this "myObject", modifying the values and saving the modified values to server.

Recent task came up to centralize this saving mechanism, whenever "SharedService.myObject"'s values are changed, this centralized saving mechanism will save the values.

export class SharedService {
   myObject: MyClass;
}

// This interface is auto generated by API
export interface MyClass {
   id?: number;
   someArray?: Array<SomeOtherInterface>;
   someOtherObject: SomeOtherInterface;
}

I tried one solution with 'getter' and 'setter' but setter is not being executed whenever "myObject" values are changed.

export class SharedService {
   _myObject: MyClass;
   get myObject() {
     console.log('tracking changes' + JSON.stringify(this._myObject));
   }

   // Setter is not being called upon any change in myObject
   set myObject(myObject: MyClass) {
     console.log('Values changed pre -> ' + JSON.stringify(this._myObject));
     console.log('Values changed new -> ' + JSON.stringify(this.myObject));
   }
}

Is there any way, I can track changes in this SharedService itself without modifying all the existing components.


Solution 1:

You could use this technique. On Your service :

export class SharedService {
   _myObject: MyClass;
   get myObject(): MyClass {
     console.log('tracking changes' + JSON.stringify(this._myObject));
return this._myObject

   }

   // Setter is not being called upon any change in myObject
   set myObject(newSate: MyClass) {
     console.log('Values changed pre -> ' + JSON.stringify(this._myObject));
     console.log('Values changed new -> ' + JSON.stringify(this.myObject));
//new lines
this._myObject = {...this._myObject,...newState}

   }
}

Lets suppose You want to change someArray data inside a class has an instance of this service:

let someArray = [1,2,3,4,5,6]
let newState : MyClass = {someArray};
//(commit) your new State
this.sharedService.myObject = newState;

// If You have a template depend to this state its state will change reactively.

//example all your template variable should to depend to state reference.

Suppose You have ngFor directive use someArray as an array

get someArray(){return sharedService.myObject.someArray }

get function is a computed function only running when there is a new update;