Search code examples
angularstatelessstateful

Angular 2 stateless or stateful?


So here is my problem. I have this component here which edits a contact passed through the input. This code works and the contact parameters are changed when i change something in the input text ( two way databinding ) and then "saved" when a hit save and route to another component ( which displays a list of all contacts ).

import {Component} from 'angular2/core';
import {Contact} from "./contact";
import {Router} from "angular2/src/router/router";
import {OnInit} from "angular2/src/core/linker/interfaces";
import {ContactService} from "./contacts.service";

@Component({
    selector:'editor',
    template:`
    <div class='editor'>
        <label>Edit name : </label><input type="text" [(ngModel)]="contact.name">
        <br>
        <label>Edit email : </label><input type="text" [(ngModel)]="contact.email">
        <br>
        <label>Edit phone number: </label><input type="text" [(ngModel)]="contact.phone">
        <br>
        <div class="description">
        Description: 
        <br>
        <textarea rows="4" cols="50" [(ngModel)]="contact.description"></textarea>
        </div>
        <br>
        <input type="button" (click)="onCreateContact()" class="button" value="Save Changes"/>
    </div>
`,
    inputs:["contact"],
    styles:[
      `
        label {
          display: inline-block;
          width: 145px;
          border-left: 3px solid #006ec3;
          padding-left: 8px;
          padding-bottom: 8px;
        }
        .description{

          border-left: 3px solid #006ec3;
          padding-left: 8px;
          padding-bottom: 8px;
        }
      `
    ]
})

export class ContactEditorComponent implements OnInit{

    public contact:Contact;

    constructor(private router:Router){

    }

    onCreateContact(){
      this.router.navigate(['Contacts']);
    }

}

Now if i change my class this way by adding a temp:Contact variable which takes a clone of my contact , changing the temp variable then cloning it to the contact object , the changes are not saved anymore when i hit the button.

@Component({
    selector:'editor',
    template:`
    <div class='editor'>
        <label>Edit name : </label><input type="text" [(ngModel)]="temp.name">
        <br>
        <label>Edit email : </label><input type="text" [(ngModel)]="temp.email">
        <br>
        <label>Edit phone number: </label><input type="text" [(ngModel)]="temp.phone">
        <br>
        <div class="description">
        Description: 
        <br>
        <textarea rows="4" cols="50" [(ngModel)]="temp.description"></textarea>
        </div>
        <br>
        <input type="button" (click)="onCreateContact()" class="button" value="Save Changes"/>
    </div>
`,
    inputs:["contact"],
    styles:[
      `
        label {
          display: inline-block;
          width: 145px;
          border-left: 3px solid #006ec3;
          padding-left: 8px;
          padding-bottom: 8px;
        }
        .description{

          border-left: 3px solid #006ec3;
          padding-left: 8px;
          padding-bottom: 8px;
        }
      `
    ]
    }) 

export class ContactEditorComponent implements OnInit{

    public contact:Contact;
    public temp:Contact;
    constructor(private router:Router){

    }

    onCreateContact(){
      this.contact = (<any>Object).assign({}, this.temp);
      console.log(this.contact.name);
      this.router.navigate(['Contacts']);
    }

  ngOnInit(){
      this.temp = (<any>Object).assign({}, this.contact);
  }
}

All my contacts are saved in another file containing a Const array of contacts and accessed through a contact.service.


Solution

  • That has nothing to do with Angular, and everything to do with JavaScript.

    Here's an example:

    const parent = {};
    parent.contact = {id: 'c1'};
    const child = {};
    child.contact = parent.contact;
    

    Now both child.contact and parent.contact are references to the same object. So

    child.contact.id = 'c2';
    console.log(parent.contact.id);
    

    will print 'c2'.

    That's what you're doing in your first example.

    Now your second example does:

    const parent = {};
    parent.contact = {id: 'c1'};
    const child = {};
    child.contact = parent.contact;
    child.temp = {id: 'c1'}; // clone of child.contact
    

    So now, child.temp references a new object, that is different (a copy) from child.contact and parent.contact.

    Then you're modifying the id of the temp contact:

    child.temp.id = 'c2';
    

    Then, when saving, you're doing

    child.contact = {id: 'c2'}; // clone of child.temp
    

    So now you have 3 different objects: one that is references by parent.contact, and which still has 'c1' as id, child.temp which is a modified copy of parent.contact, and child.contact which is yet another copy of child.temp.

    If you want to change the value of the id of the object referenced by child.contact and parent.contact, you need, instead to do

    child.contact.id = temp.contact.id;
    

    or, in your example:

    Object.assign(child.contact, temp.contact);