1

This is beginners question.. I have been reading Angular2 documentation, I came across example in Hierarchical Dependency Injectors chapter where Restore service is used to make save/cancel functionality available for editing.

This is the service:

export class RestoreService<T> {
   originalItem: T;
   currentItem: T;
 setItem (item: T) {
   this.originalItem = item;
   this.currentItem = this.clone(item);
 }
 getItem () :T {
   return this.currentItem;
 }
 restoreItem () :T {
   this.currentItem = this.originalItem;
   return this.getItem();
 }
 clone (item: T) :T {
   return JSON.parse(JSON.stringify(item));
 }
}

I was so excited about it so I tried it myself! First I'm setting the values like this:

ngAfterContentInit(){
     this.metadata = {
      languages: this.selected_languages,
      countries: this.selected_countries,
      international: false
     }
 }
 set metadata(metadata: CvMetadata){
      this._restoreService.setItem(metadata);
 }
 get metadata(): CvMetadata{
    return this._restoreService.getItem();
 }

After that I'm changing metadata properties values with ngModel for example: [(ngModel)]="metadata.languages[0]"

The question:
For my sruprise When I update the metadata property value with ngModel it works - the currentItem has changed and the orginalItem has not! What I do not understand is how is that possible? I thought that ngModel would use setter for setting the metadata properties. But the setter is called only once when I set the original data. How does the ngModel know that it should change only the currentItem not he originalItem? Is this the black magic?

I know.. I only need someone to explain this, but unfortunately or fortunately there are only you guys!

Thanks!

micronyks
  • 54,797
  • 15
  • 112
  • 146

1 Answers1

1

RestoreService: it has two functions setter and getter;

setItem (item: T) sets originalItem, clones it and save the clone to currentItem.

getItem() just returns currentItem (the cloned item)

Now, ngModel gets the item metadata in order to get its property languages. So it will get currentItem. When ngModel sets a new property value, it doesn't need to set metadata(). it only need to set languages property inside metadata. So, it will get metadata again and sets the languages property.

Here is a plunker hopefully it will help

Another way of explaining it:

this.metadata = {language:['english']}; // you set metadata, effectively setting originalItem and cloning it to currentItem

this.metadata.languages = ['arabic'];  // you get metadata "currentItem", set its property languages. Never actually setting metadata itself

Note on the clone function: the function clone in RestoreService is not cloning the object in a "practical" way. Because it uses JSON parser. See these question for more details and better cloning approaches: 122102, 728360

Community
  • 1
  • 1
Abdulrahman Alsoghayer
  • 16,462
  • 7
  • 51
  • 56